Go to production
A prototype puts a provider key in the app. A shipped app must not — keys are extractable from any binary. In production you name an agent profile, and AgentKit Cloud resolves the provider, model, system prompt, and tool schemas server-side.
One line changes
.backendRouterCloud(
endpoint: URL(string: "https://api.agkit.cloud/v1/agent/stream")!,
agentId: "video-editor",
tier: "pro",
maxOutputTokens: 2048, // a ceiling you propose; the cloud clamps it
publishableKey: "ak_pk_live_…", // public app identifier — safe to embed
userToken: endUserJWT // the real auth: a short-lived signed JWT
)
Your domains, guards, and UI don't change. Tools still execute on-device — the backend never touches your app state.
Why a profile, not a key
- No app update to change models. A new model, or switching providers for cost, is a server-side profile change. The app never knew which model it was using.
- Many agents per project.
agentIdselects the use case (video-editorgets a top model,assemblera cheaper one);tierselects the capability level per user (provsfree). The pair resolves to a model in the cloud. - No secrets in the binary. The publishable key is a public identifier,
like a Stripe
pk_. The only credential that authorizes a request is the short-lived user JWT, verified by signature server-side.
The JWT comes from an issuer the cloud trusts for your project — Sign in with
Apple, Firebase Auth, or your own backend. For per-request token refresh and
App Attest, use the signer: overload. Both are covered in
AgentKit Cloud.
Keep an offline path
The on-device model runs behind the same domains with no key and no network (it requires macOS 26+ / iOS 26+ / visionOS 26+, so the branch carries an availability check). A common pattern is to branch once and leave everything else untouched:
let provider: AgentProviderSpec
if !isOnline, #available(macOS 26.0, iOS 26.0, visionOS 26.0, *) {
provider = .appleFoundationModels()
} else {
provider = .backendRouterCloud(endpoint: endpoint, agentId: "editor", tier: tier,
maxOutputTokens: 2048,
publishableKey: publishableKey, userToken: jwt)
}
See on-device with Apple for what the small model can and can't do.
The checklist
- Switch the provider line to
.backendRouterCloud(...)— no provider key, no model name in the app. - Define each
(agentId, tier)profile in the cloud. Your executors must cover the tool names those profiles enable. - Mint a short-lived end-user JWT from a trusted issuer; embed only the publishable key.
- Handle typed cloud errors with their retry guidance — see when it fails.
- Keep an on-device fallback behind the same domains if your app should work offline.