Moya
Network abstraction layer for Swift iOS/macOS built on top of Alamofire — provides type-safe API endpoint definitions using enums and protocol-based routing. Moya TargetType protocol: each API endpoint is an enum case with associated path, method, task (parameters), headers, and sampleData (for testing). MoyaProvider<AgentAPI> wraps Alamofire session and handles requests. Supports RxSwift (RxMoya), Combine (CombineMoya), and callback-based async. Plugin system for logging, auth token injection, activity indicators. Makes API calls testable by stubbing sampleData without network. Removes boilerplate of manual URLRequest construction.
Score Breakdown
⚙ Agent Friendliness
🔒 Security
Never hardcode agent API keys in TargetType headers; use Keychain or environment config. Moya's NetworkLoggerPlugin logs all request headers in debug builds — ensure it's disabled in production to prevent agent auth token exposure in logs. sampleData files should not contain real API credentials.
⚡ Reliability
Best When
Your iOS agent app makes calls to multiple REST API endpoints and you want type-safe, testable, organized networking code — Moya's TargetType enum pattern makes API contracts explicit and mockable.
Avoid When
You only make 1-2 API calls, you're using SwiftUI with async/await URLSession directly, or you need non-REST protocols (GraphQL, WebSocket).
Use Cases
- • Type-safe agent API client — enum AgentAPI: TargetType { case listAgents; case createAgent(params: [String: Any]); case getAgent(id: String) } defines all agent endpoints in one file with compile-time safety
- • Moya plugin for agent auth token injection — AccessTokenPlugin(tokenClosure: { _ in authToken }) automatically adds Authorization header to all agent API requests without manual header management in each call
- • Unit test agent networking without mock server — provider.stubbing(.immediate) with sampleData in TargetType returns fake agent API responses in tests; no network required for agent UI unit tests
- • Combine-based agent API calls — provider.requestPublisher(.listAgents).map(AgentListResponse.self).sink handles agent API responses in reactive Combine pipeline for agent SwiftUI views
- • Moya logging plugin for agent debug — NetworkLoggerPlugin(configuration: .init(logOptions: .verbose)) logs all agent API requests and responses to console; disable in production with conditional plugin registration
Not For
- • Simple single-endpoint apps — if your agent app only makes 1-2 API calls, Moya's TargetType protocol adds unnecessary structure; use URLSession or Alamofire directly for simple agent network calls
- • Non-Alamofire networking stacks — Moya is tightly coupled to Alamofire; for agent apps using URLSession directly or other networking libraries, build a thin wrapper without Moya overhead
- • REST APIs only — Moya handles REST well but GraphQL, WebSocket, or gRPC agent APIs need supplementary libraries or a different architecture
Interface
Authentication
Moya auth via AccessTokenPlugin for Bearer tokens, or custom PluginType for API key injection. Token refresh requires custom plugin with Alamofire RequestInterceptor.
Pricing
Moya is MIT licensed. Free for all use.
Agent Metadata
Known Gotchas
- ⚠ MoyaProvider must be retained strongly — MoyaProvider<AgentAPI>() as local variable gets deallocated before request completes; store provider as property on ViewModel/Controller; weak provider causes agent API calls to silently cancel mid-request
- ⚠ sampleData must be non-empty for stub mode — stubbing returns sampleData immediately; empty sampleData (Data()) causes MoyaError.jsonMapping when response is mapped; always provide realistic sample JSON in TargetType.sampleData for agent API test stubs
- ⚠ Token refresh with AccessTokenPlugin is not automatic — AccessTokenPlugin injects static token at request time; expired tokens require custom RequestInterceptor wrapping Alamofire session to handle 401 → refresh → retry flow; Moya does not handle token refresh automatically for agent auth
- ⚠ Reactive subscriptions need disposeBag retention — RxMoya: provider.rx.request(.listAgents).subscribe() disposable must be added to disposeBag; without disposeBag, subscription cancels immediately on method return; store disposeBag on ViewModel for agent reactive networking
- ⚠ multipart upload via .uploadMultipart task — file upload to agent API requires task: .uploadMultipart([MultipartFormData(...)]) not .requestParameters; using wrong task type for file uploads causes request to send without file body; check task enum carefully for agent document upload endpoints
- ⚠ Plugin order matters for auth + logging — plugins are called in array order; [NetworkLoggerPlugin(), AccessTokenPlugin(...)] logs before token injection (missing auth header in log); reverse order [AccessTokenPlugin(), NetworkLoggerPlugin()] logs actual request with auth header; order plugins intentionally for agent API debugging accuracy
Alternatives
Full Evaluation Report
Comprehensive deep-dive: security analysis, reliability audit, agent experience review, cost modeling, competitive positioning, and improvement roadmap for Moya.
AI-powered analysis · PDF + markdown · Delivered within 30 minutes
Package Brief
Quick verdict, integration guide, cost projections, gotchas with workarounds, and alternatives comparison.
Delivered within 10 minutes
Score Monitoring
Get alerted when this package's AF, security, or reliability scores change significantly. Stay ahead of regressions.
Continuous monitoring
Scores are editorial opinions as of 2026-03-07.