Build with Narad Protocol.
The @devkrity/narad, @devkrity/narad-spec, and @devkrity/narad-react packages are released at version 0.1.0 under MIT.
Install the packages
npm install @devkrity/narad @devkrity/narad-react @devkrity/narad-spec
Validate wire records, reduce ordered events into current state, replay history, and coordinate live delivery with backfill. The toolkit also includes interrupt commands and leased client tool execution.
React bindings
A provider and snapshot/selector hooks connect React to the Narad store. Bring your own interface and transport; the bindings do not supply a complete chat application.
The contract
Inspect the versioned specification, JSON schemas, and conformance traces. Read narad/v1 or browse the source.
Replay a JSONL trace
This example replays the interrupt-pause.jsonl conformance trace from @devkrity/narad-spec into the reducer. It reports applied, duplicate, and gap counts, plus any errors, then prints the resulting snapshot.
import { createNaradReducer, replayJsonlReducer } from '@devkrity/narad';
const trace = `{"type":"run.started","protocolVersion":"narad/v1","eventId":"evt-1","timestamp":"2026-08-05T00:00:00Z","sessionId":"session-3","sessionSequence":1,"rootRunId":"run-3","runId":"run-3","sequence":1}
{"type":"interrupt.requested","protocolVersion":"narad/v1","eventId":"evt-2","timestamp":"2026-08-05T00:00:01Z","sessionId":"session-3","sessionSequence":2,"rootRunId":"run-3","runId":"run-3","sequence":2,"interruptId":"interrupt-1","waitId":"wait-1","kind":"approval","actions":["approve","deny"]}
{"type":"run.paused","protocolVersion":"narad/v1","eventId":"evt-3","timestamp":"2026-08-05T00:00:01Z","sessionId":"session-3","sessionSequence":3,"rootRunId":"run-3","runId":"run-3","sequence":3,"waitId":"wait-1","reason":"interrupt","resumeMode":"command","interruptId":"interrupt-1"}
{"type":"interrupt.resolved","protocolVersion":"narad/v1","eventId":"evt-4","timestamp":"2026-08-05T00:00:02Z","sessionId":"session-3","sessionSequence":4,"rootRunId":"run-3","runId":"run-3","sequence":4,"interruptId":"interrupt-1","waitId":"wait-1","decision":"approve"}
{"type":"run.resumed","protocolVersion":"narad/v1","eventId":"evt-5","timestamp":"2026-08-05T00:00:02Z","sessionId":"session-3","sessionSequence":5,"rootRunId":"run-3","runId":"run-3","sequence":5,"waitId":"wait-1"}
{"type":"run.finished","protocolVersion":"narad/v1","eventId":"evt-6","timestamp":"2026-08-05T00:00:03Z","sessionId":"session-3","sessionSequence":6,"rootRunId":"run-3","runId":"run-3","sequence":6}`;
const reducer = createNaradReducer({ sessionId: 'session-3', activeProfiles: [] });
const result = replayJsonlReducer(reducer, trace.split('\n'));
console.log({
applied: result.applied,
duplicates: result.duplicates,
gaps: result.gaps,
errors: result.errors,
});
console.log(reducer.getSnapshot());
Your backend owns the work
Narad reconstructs the client view from the history your application provides. Your backend persists that history, authorises commands, and executes or continues runs. Reconnecting a client does not restart or resume execution by itself.