Nested agents
A child agent is linked to the exact tool call in the parent that started it, and the whole tree shares one root run. An approval asked deep inside the tree can show up where the person is already looking.
parentToolCallId↗Narad (NAA-rud, नारद) is named after the sage of Indian mythology who carries messages between worlds.
Agents that call agents, workflows that branch and wait for a person, tools that run on the user’s machine. Narad Protocol builds these into the protocol between your agent host and every client, with strict rules so they all agree on what’s running, what’s waiting and who can act.
npm install @devkrity/naradroot run · sessionSequence 001child agent as a tool · sessionSequence 002child run · parentToolCallId · sessionSequence 003actions approve · deny · sessionSequence 004resumeMode command · sessionSequence 005decision approve · sessionSequence 006Narad started inside Kautuka. Runs can span nested agents, workflow branches, human decisions and clients that reconnect later. Narad defines ordered events from the host and client rules for following runs, catching up and requesting decisions.
These projects cover different layers: MCP defines access to tools and context; A2A defines communication between agents; AG-UI carries agent events into user-facing apps. Narad defines run and workflow state between a host and its clients.
The core covers runs, tools and approvals, with strict lifecycle rules. Conversation, state, graphs, progress and more are optional profiles that the host and client agree on when a client attaches.
A child agent is linked to the exact tool call in the parent that started it, and the whole tree shares one root run. An approval asked deep inside the tree can show up where the person is already looking.
parentToolCallId↗Steps, attempts and the branch actually taken are recorded with their own workflow sequence, so a client can draw the route the work took. A workflow can pause for a person, just like a run.
workflow.edge.taken↗An approval is a named question with the choices on offer and an optional expiry. Asking, pausing, answering and resuming are separate facts, and one approval can carry a decision for each of several tools.
interrupt.requested↗Designed into the protocol: the host targets one device under a lease and sends an expiring, single-use token. A tool runs once, on the right machine, and never because someone replayed history.
executionToken↗Every fact gets a host-assigned place in order, and duplicates are ignored. Clients refuse illegal steps, such as a paused run finishing before it resumes or an answer that wasn’t offered. A gap means catch up, never guess.
sessionSequence↗Authority events are facts the host appends in order. A web app, a terminal and a chat bridge reduce the same facts into the same view. Clients never change state directly: they send commands, and the host’s answer shows up as new facts. If two people answer the same approval, the host decides once and every client sees the same result.
Watch messages announce scoped changes. Hydrate records provide derived views anchored to an authority cursor. Control messages carry attach, heartbeat, and targeted client-tool execution.
Seeing that a tool was called never runs it. Running a tool on a client takes targeted control, with an executor identity, a lease and an expiring token.
Timestamps provide context. Authority order comes from sequence values assigned by the host.
| Scope | Field | Ordered within |
|---|---|---|
| Session | sessionSequence | Session authority events |
| Workflow | workflowSequence | Events in that workflow |
| Run tree | sequence | Events under the root run |
eventId supports stable deduplication. Timestamps never change the order.
Attach subscribes first, buffers live records, backfills history, then drains the buffer. A sequence gap triggers a catch-up from the known cursor.
Catching up rebuilds client state. Execution recovery and durable storage remain host responsibilities.
Because every change is an ordered fact from the host, reconnecting is just catching up. Narad Protocol’s attach coordinator joins history with buffered live delivery, so a client that drops off rebuilds the same view of what’s running and what’s waiting.
This reconstructs client state. It does not restart a run or recover interrupted host work.
Read the session attach rulesOpen live delivery before requesting history.
Hold incoming records while history is fetched.
Apply ordered history, then drain buffered events against the reducer cursor.
Fetch from the known sequence before the client continues.
{"type":"run.started","sessionSequence":1}
{"type":"interrupt.requested","sessionSequence":2,
"kind":"approval","actions":["approve","deny"]}
{"type":"run.paused","sessionSequence":3,"waitId":"wait-1"}
{"type":"interrupt.resolved","sessionSequence":5,
"waitId":"wait-1","decision":"approve"}
{"type":"run.resumed","sessionSequence":6,"waitId":"wait-1"}
{"type":"run.finished","sessionSequence":7}@devkrity/narad-specNormative protocol, JSON Schemas, and conformance traces.
@devkrity/naradWire validation, reducer and store, replay, SSE frame parser, attach coordinator, command client, and client executor.
@devkrity/narad-reactProvider and selector hooks over an existing store; no session creation or transport ownership.
TypeScript · React bindings · MIT
Narad Protocol grew out of Kautuka, and it’s designed to work with any agent host. Explore Kautuka ↗
Narad Protocol defines the rules and client-side state machinery—not a server, scheduler, history store, authorisation system, or agent runtime. The host supplies those responsibilities; persistence and execution guarantees depend on that implementation.