Skip to main content
Short answers to specific questions. Each section shows the minimum code to wire pieces together — partial snippets across files, not full apps. Fifteen topics below; use the table of contents to jump.

How to communicate between frontend and agent

The browser POSTs to an exposed route; the network publishes a start event on the main channel; agents emit to a client channel with proxy.sse(); the response streams back as SSE.

Define events

Wire the network and expose SSE

Read the stream in React

See Streaming and IO + Adapters.

How to stream LLM tokens to the client

Emit one event per token (or chunk) with isFinal: false, then a terminal chunk with isFinal: true. The client channel SSE proxy forwards each emit to the browser.

Define a stream chunk event

Emit chunks from agent logic

Register the agent on a channel with proxy.sse() so chunks reach the HTTP client. See examples/core-example/app/sse/api/example-agent.ts.

How to add tools to an agent

Define tools with Tool.of(), attach them via .tools([...]) on the agent factory, and call them inside .logic() through tools.toTools() or the bound collection.

Define a tool

Attach tools to the agent

Tools can emit events (for UI side-effects) and depend on dependency layers for shared services. See examples/assistant-app/src/network/tools/.

How to chain agents across channels

Use extra channels so one agent’s output becomes another agent’s input. Subscribe each agent to the channels it should listen on; publish to the channels downstream agents or the client should see.

Main assistant + background worker

The main agent handles user messages on mainChannel and can emit task events onto sub. The worker subscribes to sub only — it never sees raw HTTP traffic.
See Patterns: Agent Chain and examples/assistant-app/src/network/network.ts.

How to delegate work and wait for a reply

Use emitAndAwait inside agent logic or tool handlers to emit an event and pause until a matching reply arrives on the network (scoped by correlationId).

From a tool — spawn a sub-agent

The worker on the sub channel must emit SubAgentTaskCompleted while the tool is waiting. Correlation ids are copied from the triggering event meta, so the matcher only accepts the paired reply.

From agent logic

The reply must come from a different subscriber while the caller is blocked — same-agent loopbacks time out. See Patterns: Loopback.

How to add auth to an exposed endpoint

Reject unauthenticated requests before any start event is published. Return { allowed: false, status, message } from the auth callback on registerSSEStream.
Forward the same header from the client fetch call. See Auth + Multi-Tenant.

How to pass user or tenant context into events

Enrich the start event in onRequest so agents receive userId, tenantId, or other scope fields in the payload.
Use contextId from the request (or a header like x-correlation-id) to group events for the same conversation.

How to use conversation history in agent logic

contextEvents exposes prior events for the current contextId. Filter by event type to rebuild chat history before calling an LLM.
runEvents contains events from the current run only; contextEvents spans the full conversation context.

How to aggregate stream events

Use EventAggregator to watch a stream of chunk events and emit a derived event when a condition is met — without adding another full agent.
See examples/core-example/app/sse/api/network.ts for a working aggregator on the client channel.

How to filter which events the client receives

Limit the SSE stream to specific event names so internal or debug events never reach the browser.
You can also declare allowed events on the channel itself:

How to handle errors and surface them to the UI

Define an error event, emit it from a try/catch in agent logic, and include it in the SSE filter so the client can render failures.

How to inject shared services with dependency layers

Declare layers on the network, implement them with .make(), and pass instances when starting the runtime. Agents and tools access services through layers.LayerName.

Define and register a layer

Provide layer instances at runtime

For a long-lived server, start the plane once and reuse it across requests:
See examples/assistant-app/src/server/assistant-runtime.ts.

How to run multiple agents in parallel

Subscribe several agents to the same channel so one incoming event triggers all of them at once. Each agent can publish to the same or different output channels.
Use this for parallel side-effects (logging, metrics, processing) on the same trigger. See Patterns: Fan-Out.

How to add tracing to agent runs

Pass a networkTracer when setting up the network. Agents receive a tracing scope in .logic() to record LLM and tool spans.
Every event carries meta.runId, meta.contextId, and meta.correlationId for correlation. See Error Handling + Observability.

How to reuse streaming logic with a skill

Extract reusable streaming behavior into a Skill, then call invokeStream() from an agent and map chunks to network events.
Skills are testable units; agents handle event wiring. See examples/core-example/skills/reasoning.skill.ts.

How to spawn agents at runtime

Use spawner to create agents on demand when a spawn event arrives — useful for per-tenant or per-session workers.
The spawn event payload can carry tenantId or custom params; onSpawn selects the factory and calls spawn(agent) to register bindings. See Auth + Multi-Tenant.