A zone app is a separate Next.js application that provides a custom UI for a single agent. Zones are useful when the agent needs richer interaction than the platform's built-in input/output pages can provide — interactive review screens, complex multi-step inputs, custom dashboards.
How it works
- You build and deploy a Next.js app — your zone.
- A platform admin registers the zone's URL and a shared JWT secret against an agent.
- When a user navigates to
/{orgSlug}/{agentSlug}/app/*on the platform, the platform mints a per-request JWT signed with the agent'szone_jwt_secretand rewrites the request to your zone. - Your zone verifies the JWT (via
createZoneMiddleware), reads the claims (viagetSession), and calls platform endpoints on the user's behalf (viacreateZoneClient).
From the user's perspective, the zone feels like a native part of the platform — same URL, same auth, same navigation.
Request flow
Browser
│ GET https://platform.tld/{orgSlug}/{agentSlug}/app[/...]
▼
Platform middleware
• reads the platform session → { userId, orgId, agentId, role }
• mints a per-request HS256 JWT with the agent's zone_jwt_secret
• rewrites to the zone, forwarding the JWT as `x-zone-token`
▼
Zone middleware (createZoneMiddleware)
• verifies `x-zone-token` against ZONE_JWT_SECRET
• attaches decoded claims on `x-zone-claims`
▼
Zone page or server component
• reads { claims, token } via getSession()
▼
Zone server action
• forwards `token` as `Authorization: Bearer` to a platform zone endpoint
▼
Platform `/api/zones/agents/{agentId}/runs[…]`
• re-verifies the token, cross-checks agentId in the URL against the claim,
then executes the requested operation
The zone owns the entire /app/* subtree — /app, /app/runs, /app/settings, and any other routes it defines. The platform reserves only the /app/* prefix.
Static assets are served on the same origin: the browser fetches /assets/{orgSlug}/{agentSlug}/_next/* from the platform, which proxies to the zone. Same-origin asset delivery is load-bearing — see Deploy for why.
Deep-linking
Anything that needs to link to a specific run from outside the zone (HITL emails, Slack notifications, dashboards) uses:
/{orgSlug}/{agentSlug}/app?run=<runId>
Honour this query param in your landing page — the platform's HITL notification system routes zone-backed agents to /app?run=<runId> automatically, and dropping the convention breaks those links.
What lives in the zone vs. the platform
| In the zone | In the platform |
|---|---|
| Bespoke UI for this agent | Org / user / role management |
| Domain-specific workflows | Run history and observability |
Run triggering via createZoneClient | Run execution via the runtime |
| Custom layouts and components | Auth, RBAC, billing, settings |
The zone never holds long-lived platform credentials. Every request comes with a fresh JWT scoped to the agent and the user.
Prerequisites
- Node 20+
- A registered agent on the platform (a platform admin will share
zone_jwt_secretand audience). - Familiarity with Next.js App Router.
Walkthrough
The remaining pages in this section walk through a complete zone build:
- Scaffold — Next.js project setup,
basePath,assetPrefix,allowedOrigins. - Auth — verifying the zone JWT.
- Session — reading claims in server components.
- Platform client — triggering runs, resolving credentials.
- Deploy — registering the zone and going live.