Ch9. Channels, Auth, Streaming
How Eve channels own session creation, continuation tokens, route auth, NDJSON streams, and frontend/client integration.
핵심 요약
- A channel is the agent's front door: auth, input normalization, session cursor ownership, and delivery.
- Route auth fails closed, but session ownership ACLs are still the application/channel's responsibility.
- A continuation token is not a queue; ordering and burst handling belong in the channel/app layer.
If a channel is wrong, model quality and tool safety cannot save the system. Channels decide who can enter, which session they resume, and where results or human prompts are delivered.
Channel Responsibilities
| Responsibility | Description |
|---|---|
| input normalization | turn Slack, HTTP, GitHub, etc. into user messages |
| continuation ownership | map a thread/conversation/job to a continuation token |
| delivery | send responses, failures, approvals, and auth prompts |
The default Eve HTTP channel exposes POST /eve/v1/session, POST /eve/v1/session/:sessionId, and GET /eve/v1/session/:sessionId/stream.
Default Eve HTTP Channel
If you do not author agent/channels/eve.ts, Eve provides a framework default. You usually author the file to customize route auth.
import { eveChannel } from "eve/channels/eve";
import { localDev, vercelOidc } from "eve/channels/auth";
export default eveChannel({
auth: [localDev(), vercelOidc()],
});Official Auth & Route Protection distinguishes framework default from scaffolded auth:
| Case | Auth | Meaning |
|---|---|---|
no authored eve.ts | [localDev(), vercelOidc()] | localhost and Vercel OIDC callers only |
eve init scaffold | [localDev(), vercelOidc(), placeholderAuth()] | structured production 401 until real auth is configured |
placeholderAuth() is a guardrail, not a production auth policy.
Route Auth Fails Closed
| AuthFn result | Meaning |
|---|---|
returns SessionAuthContext | success, stop the walk |
returns null/undefined | continue to next AuthFn |
| throws | reject with 401/403 |
| all skip | reject with 401 |
Anonymous access requires explicit none().
Route Auth Is Not Session Ownership
If multiple users can call the same Eve route, you still need a session ownership check.
Danger:
any signed-in user -> Eve route
knows sessionId or continuationToken
can follow up or stream another tenant sessionRecommended structure:
| Layer | Standard |
|---|---|
| route auth | authenticate user or service |
| session mapping | store sessionId -> owner/tenant/channel |
| follow-up guard | principal must own or participate in session |
| stream guard | stream endpoint enforces the same ownership |
Continuation Token Is Not A Queue
continuationToken resumes the current session hook. It is not a FIFO queue. If many messages arrive concurrently, ordering must be handled outside Eve.
Operating patterns:
- send the next user turn after
session.waiting - use per-session queues for bursty chat platforms
- separate approval responses from new messages
- persist the latest session cursor and reject stale usage
NDJSON Stream
GET /eve/v1/session/:sessionId/stream returns newline-delimited JSON events.
| Event | Meaning |
|---|---|
session.started | durable session created |
turn.started | user turn started |
step.started | model step started |
actions.requested | tool/subagent calls requested |
action.result | action result |
input.requested | approval, question, or OAuth needed |
subagent.called | child session available |
message.appended | assistant text delta |
message.completed | assistant message completed |
result.completed | structured output completed |
step.failed/turn.failed/session.failed | failure boundary |
session.waiting | waiting for next input |
Reasoning events and tool results may need privacy and retention controls.
Event Dispatch Order
- Channel handler runs and updates adapter state.
- Stream event is durably recorded.
- Hooks run.
- Dynamic tool/skill/instruction resolvers run.
This lets dynamic resolvers depend on channel metadata projected by channel handlers.
Custom Channels
import { defineChannel, POST } from "eve/channels";
export default defineChannel({
routes: [
POST("/incident", async (req, args) => {
const incident = await req.json();
args.waitUntil(
args.send(`Investigate incident ${incident.id}`, {
auth: {
authenticator: "incident-service",
principalType: "service",
principalId: incident.actorId,
attributes: { incidentId: incident.id },
},
continuationToken: `incident:${incident.id}`,
}),
);
return new Response("ok");
}),
],
});Review:
- HMAC/JWT/OIDC raw request authentication
- never trust body-supplied principals
- constant-time signature comparison
- continuation token stability
- file upload fetch policy
- failure delivery
Official Channel Integrations
| Channel | Official docs | Enterprise point |
|---|---|---|
| Eve HTTP | eve | session and stream routes |
| Custom | Custom Channels | HTTP/WS, metadata, cross-channel hand-off |
| Slack | Slack | thread anchoring and private auth challenges |
| Discord | Discord | slash commands, components, modals |
| GitHub | GitHub | PR diff context and sandbox checkout |
| Linear | Linear | Agent Sessions and Agent Activities |
| Teams | Microsoft Teams | Bot Framework and Adaptive Cards |
| Telegram | Telegram | inline-keyboard HITL |
| Twilio | Twilio | SMS/voice compliance review |
Client And Frontend
Use TypeScript SDK for scripts, tests, and server-to-server calls. Use frontend helpers for browser chat or agent UI.
| Topic | Standard |
|---|---|
| resumable sessions | persist the full cursor: sessionId, continuationToken, streamIndex |
clientContext | per-turn ephemeral context, not durable session history |
| HITL response | answer input.requested with inputResponses on the same session |
| framework integration | Next.js withEve, Nuxt module, SvelteKit plugin |
Checklist
| Item | Standard |
|---|---|
| route auth | no placeholder in production |
| session ACL | principal and tenant mapping |
| stream ACL | stream endpoint protected |
| continuation | latest cursor persisted; stale rejected |
| ordering | per-session queue if needed |
| metadata | project only safe values |
| signatures | constant-time verification |
| eval | 401, 403, and valid stream cases |
Ch8. Sandbox Secure Runtime
Turn Eve sandbox trust boundaries, backends, network policy, credential brokering, and workspace lifecycle into operating standards.
Ch10. Subagents, Workflows, Remote Agents
Use Eve built-in agent tool, declared subagents, remote agents, and experimental Workflow for multi-agent design.