The protocol for real-world agent systems.

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/narad

Narad 0.1.0 · MIT · npm package · GitHub source

ONE RUN TREE · ONE ANSWER Illustrative trace · narad/v1

Why Narad Protocol exists

Narad 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.

Built into the protocol

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.

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↗

Workflows that branch and wait

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↗

First-class approvals

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↗

Client-side tools, fenced

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↗

Strict rules every client checks

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↗
Optional profilesconversationattachmentsartifactsstate · UIgraphprogressworkspacetrace · debug

The host states facts. Clients send requests.

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.

Host and clients in Narad Protocol The host owns authority. It appends authority events, facts, in order by session sequence, and keeps a run tree where a child run is linked to the parent tool call by parentToolCallId. It decides each approval once. Web, terminal and chat clients send commands, which are requests, not authority, and each reduces the same facts to the same view. After a reconnect a client attaches, backfills and catches up. A client-side tool runs on one device, with a lease and an expiring, single-use token. Host Owns authority. Decides each approval once. Authority events · facts, in order 1 run.started 2 tool.call.started 3 run.started parentToolCallId 4 interrupt.requested 5 run.paused 6 interrupt.resolved decided once sessionSequence Run tree parent run tool call child run parentToolCallId Web client Reduces the same facts to the same view Terminal client Reduces the same facts to the same view Chat client Reduces the same facts to the same view Facts (authority events) Commands: requests, not authority Reconnect: attach · backfill · catch up Client-side tool Runs on one device · a lease · an expiring, single-use token
Facts flow out from the host; requests flow back as commands.
Wire model and protocol boundaries

Order is part of the contract.

Timestamps provide context. Authority order comes from sequence values assigned by the host.

ScopeFieldOrdered within
SessionsessionSequenceSession authority events
WorkflowworkflowSequenceEvents in that workflow
Run treesequenceEvents 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.

Reconnecting is catching up.

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 rules
  1. 01

    Subscribe

    Open live delivery before requesting history.

  2. 02

    Buffer

    Hold incoming records while history is fetched.

  3. 03

    Backfill and reduce

    Apply ordered history, then drain buffered events against the reducer cursor.

  4. 04

    Catch up on gaps

    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}
Illustrative excerpt · sequence 4 is omitted; clients catch up from the known cursor before applying later events.

Specification and packages

@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

Extracted from Kautuka

Narad Protocol grew out of Kautuka, and it’s designed to work with any agent host. Explore Kautuka ↗

Clients follow the facts.
Hosts run the work.

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.