@holokai/synapse-sdk
v0.3.0
Published
Synapse — the BigBrain SDK (TypeScript): the client for driving BigBrain (chat sessions, blocks, workflows). Sibling of @holokai/neuron-sdk (which builds workers). See docs/CLIENT_SDKS.md.
Keywords
Readme
@holokai/synapse-sdk
Synapse — the BigBrain SDK for driving BigBrain from TypeScript: create chat sessions, launch blocks, run workflows.
Sibling of @holokai/neuron-sdk, pointing the other way. A neuron is a
worker BigBrain sends tasks to; a synapse is the interface that sends
intent to the brain.
neuron-sdk → build a WORKER BigBrain → you /neuron/*
synapse-sdk → DRIVE the brain you → BigBrain /chat-v2, /templates, /workflowsNothing runs here. This is a thin, typed HTTP client — no agentic loops, no
prompts, no coding opinions. Those live server-side in apps/api.
Full model and role split: docs/CLIENT_SDKS.md.
Quick start
import { createSynapse } from '@holokai/synapse-sdk';
const synapse = createSynapse({
gatewayUrlSource: () => config.gatewayUrl,
tokenSource: () => auth.getSubjectToken(), // async — refresh happens here
});
const { sessionId } = await synapse.chat.create({ goal, handlerCatalog });
const result = await synapse.chat.turn(sessionId, 'start with the tests');createSynapse(deps) returns one handle — synapse.chat,
synapse.templates, synapse.workflows, synapse.capabilities. deps is
the only injection point:
| dep | why |
| ------------------ | ------------------------------------------------------------- |
| tokenSource | Auth is injected, never implemented here. |
| gatewayUrlSource | Read per call, so a reconfiguration takes effect live. |
| fetchImpl? | Transport seam; an embedded-host IPC transport slots in here. |
| defaultTimeoutMs? | Per-instance ceiling, overridable per call. Unset = no timeout. |
Scope (v1)
Deliberately narrow. An API enters this package when a consumer needs it — not to mirror the endpoint list or the desktop's hand-rolled clients. What ships today is exactly what the first consumer (the BigBrain MCP server) calls, which is also lele Phase 1's list:
| synapse. | methods | → endpoints |
| -------------- | -------------------------------------------------------------------------- | ---------------------------- |
| chat | create / turn / supervise / list / get / cancel | /chat-v2/* |
| templates | list / get / fromTemplate / templatizePreview / templatizeCommit | the T-series template routes |
| workflows | create / get / list / start / events | /workflows, SSE |
| capabilities | list | the org capability registry |
| plan | plan / session | /plan, /plan/session |
Every method takes an optional trailing SynapseCallOptions
({ signal?, timeoutMs? }).
workflows.list() is cursor-paginated, not offset-paginated: pass the
previous page's nextCursor back in and stop when it returns null. The
token is opaque — it encodes the sort key, so the gateway rejects anything it
did not issue with INVALID_CURSOR. A status filter may be one value or
several; several are sent as repeated ?status= parameters.
plan creates nothing. Both methods return a definition you then hand to
workflows.create(). They forward to a Holo planner and re-prompt it on
type-binding violations up to a server-side budget, so they can take
meaningfully longer than the rest of this surface — that is what timeoutMs
is for, and there is no default because any value this library picked would
be wrong for somebody's model. plan.session() is stateless between turns:
feed transcript and partial_graph forward, or you start over.
Errors are one classified type: SynapseError { kind, status?, details? },
where kind is network | auth | client | server | parse.
kind alone is not always enough to branch. A supervisor failure arrives as
a thrown SynapseError — there is no { status: 'error' } result — and the
gateway's code is what distinguishes the cases:
| code | HTTP | kind |
| ----------------------------- | ---- | -------- |
| WORKFLOW_NOT_FOUND | 404 | client |
| PATCH_CONFLICT | 409 | client |
| SESSION_CANCELLED | 409 | client |
| TURN_BUDGET_EXHAUSTED | 409 | client |
| INFERENCE_ROUTE_UNAVAILABLE | 501 | server |
| HOLO_CALL_FAILED | 502 | server |
| VALIDATION_UNRESOLVED | 502 | server |
import { supervisorErrorBody } from '@holokai/synapse-sdk';
try {
await synapse.chat.turn(sessionId, msg);
} catch (err) {
const body = supervisorErrorBody(err);
if (body?.code === 'INFERENCE_ROUTE_UNAVAILABLE') { /* deployment gap */ }
}A bye event with data.reason === 'slow_consumer' ends the stream
successfully but means frames were DROPPED — reconcile with
workflows.get(). A stream that ends without any bye is truncation and
raises a network error rather than completing silently.
Deferred
Not oversights — no consumer yet, and all of it still works in the desktop's own clients. Each lands when a consumer pulls it in:
| deferred | note |
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Auth flows (device flow, token exchange, refresh) | Lives in neuron-sdk/auth. The synapse takes a tokenSource and stays credential-agnostic. A convenience re-export is a follow-up. |
| Workflow lifecycle ops (pause / resume) | The surface creates, launches, reads, streams, and cancels a chat session. |
| Neuron-hosting (register, receive leases, ack) | Wrong SDK by design — that is @holokai/neuron-sdk. A dual-role client imports both. |
| Chat v1 | Superseded by chat v2; v1 never enters the synapse. |
| Other language ports (holokai-synapse-sdk Py, synapse-sdk-go) | Demand-driven. lele's Go driver lives in its own internal/session until it stabilises. |
| Other client surfaces (neuron hosting, chat v1) | Wrong SDK / superseded — see above. |
Never in scope, at any version: agentic loops, prompts, coding opinions.
Non-breaking rule
synapse-sdk wraps existing REST endpoints and changes no server
behavior. Migrating a consumer onto this package is a separate opt-in
change, one consumer at a time.
Note the desktop tester's src/shared/chat-v2-api.ts IS modified on this
branch — it gained the per-session inference block and the ask policy. That
is its own change, not a consequence of adopting this SDK, but the earlier
claim that the desktop clients are untouched no longer holds and is corrected
here rather than left to mislead a migration estimate.
Installing
Restricted on npm, so an authenticated .npmrc for the @holokai scope is
required:
npm i @holokai/synapse-sdkDevelopment
pnpm --filter @holokai/synapse-sdk test
pnpm --filter @holokai/synapse-sdk typecheck
pnpm --filter @holokai/synapse-sdk build