Skip to content
WIP

This guide is a work in progress. Barry is also a work in progress.

@barry-rocks/sdk/sessions

Types for live sessions: turns, delivery, continuation, approvals, and the per-turn options a session adapter works with. Most bags don’t need it; session adapters and apps that drive sessions do.

import { … } from "@barry-rocks/sdk/sessions";

Events pushed by a session and pulled by its reader, each delivered once.

Buffers while nobody is reading, because a reader typically starts reading just after delivering a message — and the harness may already have answered.

Type Parameter
T
  • AsyncIterable<T>

new EventQueue<T>(): EventQueue<T>

EventQueue<T>

[asyncIterator](): AsyncIterator<T>

AsyncIterator<T>

AsyncIterable.[asyncIterator]

end(): void

Readers drain what is buffered, then stop.

void

push(item): void

Parameter Type
item T

void


A live permission callback is retained, never represented as a durable snapshot.

Property Modifier Type
approvalContinuation readonly "live"

begin(content, emit, conversation?): Promise<SegmentOutcome>

Parameter Type
content string
emit (event) => Promise<void>
conversation? ContinuationDescriptor

Promise<SegmentOutcome>

ContinuationHarness.begin

close(): Promise<void>

Promise<void>

ContinuationHarness.close

interrupt(): Promise<void>

Promise<void>

ContinuationHarness.interrupt

restore(continuation, decisions, effects, emit): Promise<SegmentOutcome>

Parameter Type
continuation ContinuationDescriptor
decisions ReadonlyMap<string, PermissionDecision>
effects ContinuationEffects
emit (event) => Promise<void>

Promise<SegmentOutcome>

ContinuationHarness.restore

validate(continuation): void

Parameter Type
continuation ContinuationDescriptor

void

ContinuationHarness.validate

static open(adapterId, fingerprint, config, start): Promise<LiveContinuation>

Parameter Type
adapterId string
fingerprint string
config SessionConfig
start (config) => Promise<Session>

Promise<LiveContinuation>


A method the session’s mode cannot perform, naming the mode that refused.

  • Error

new NotSupportedInMode(operation, mode): NotSupportedInMode

Parameter Type
operation string
mode ModeId

NotSupportedInMode

Error.constructor

Property Modifier Type
mode readonly ModeId
operation readonly string

One execution path for HTTP, apps and workflow turn receipts.

new TurnExecution(dependencies): TurnExecution

Parameter Type
dependencies TurnExecutionDependencies

TurnExecution

admit(input): TurnSnapshot

Parameter Type
input { actor: string; content: unknown; ifActive?: "error" | "queue"; policy: { mode: "automatic"; } | { expiresAt?: string; mode: "review_required"; }; requestId: string; runId: string; sessionId: string; }
input.actor string
input.content unknown
input.ifActive? "error" | "queue"
input.policy { mode: "automatic"; } | { expiresAt?: string; mode: "review_required"; }
input.requestId string
input.runId string
input.sessionId string

TurnSnapshot

cancel(sessionId, turnId): Promise<TurnSnapshot>

Parameter Type
sessionId string
turnId string

Promise<TurnSnapshot>

close(): Promise<void>

Promise<void>

recover(turn, input?, restoring?): void

Only runnable, unclaimed records are dispatched; never steal a process lease.

Parameter Type Default value
turn TurnSnapshot undefined
input? unknown undefined
restoring? boolean true

void

resolve(input): TurnSnapshot

Parameter Type
input { actor: string; context?: unknown; decisions: ApprovalDecision[]; requestId: string; runId: string; sessionId: string; turnId: string; }
input.actor string
input.context? unknown
input.decisions ApprovalDecision[]
input.requestId string
input.runId string
input.sessionId string
input.turnId string

TurnSnapshot

settled(turnId): Promise<void>

Parameter Type
turnId string

Promise<void>

Property Type
decision PermissionDecision
interruptId string

Private adapter data. Never include this value in an app snapshot.

Property Type
adapterId string
adapterVersion string
configFingerprint string
format string
harnessVersion string
payload unknown
version number

Every call goes through current authority and a persisted effect boundary.

authorize(call): Promise<PermissionDecision>

Parameter Type
call PermissionRequest

Promise<PermissionDecision>

optional denied(call, result): Promise<RecordedCallResult>

Parameter Type
call PermissionRequest
result RecordedCallResult

Promise<RecordedCallResult>

execute(call, effect): Promise<RecordedCallResult>

Parameter Type
call PermissionRequest
effect () => Promise<RecordedCallResult>

Promise<RecordedCallResult>

optional recorded(call): Promise<RecordedCallResult | undefined>

Parameter Type
call PermissionRequest

Promise<RecordedCallResult | undefined>


A quiescent segment returns before its runtime is released. The owner commits the returned checkpoint before publishing an interrupt or closing the handle.

Property Modifier Type
approvalContinuation readonly ApprovalContinuation

begin(content, emit, conversation?): Promise<SegmentOutcome>

Parameter Type
content string
emit (event) => Promise<void>
conversation? ContinuationDescriptor

Promise<SegmentOutcome>

close(): Promise<void>

Promise<void>

interrupt(): Promise<void>

Promise<void>

restore(continuation, decisions, effects, emit): Promise<SegmentOutcome>

Parameter Type
continuation ContinuationDescriptor
decisions ReadonlyMap<string, PermissionDecision>
effects ContinuationEffects
emit (event) => Promise<void>

Promise<SegmentOutcome>

validate(continuation): void

Parameter Type
continuation ContinuationDescriptor

void


Property Type Description
from? Sender -
ifActive? "queue" | "steer" Asked for, not promised: a session that cannot steer queues, and its receipt says so.
outputSchema? JsonSchema Constrains this turn’s final answer; see runStructured for harnesses that cannot.

What actually happened to a delivery, which is what the sender is told.

Property Type Description
messageId string -
status "started" | "steered" | "queued" | "held" started a new turn; steered into the running one; queued behind it; held by Barry because the harness could not take it now.

The network half of a bound, when it asks to be enforced by a sandbox rather than by guards. An empty allowlist means nothing leaves the machine.

Property Type Description
allowDomains string[] -
allowUnixSockets? string[] Unix sockets the session still needs, such as a local MCP server.

Property Type Description
description? string The harness’s own description, when it gives one.
id string -
input unknown -
tool string -

Property Type Description
guarantees Guarantees -
harnessSessionId? string The conversation to continue, when resuming one.
harnessVersion? string -
id string -

optional close(): Promise<void>

Release anything held across turns.

Promise<void>

runTurn(content, turn): AsyncIterable<SessionEvent>

Run one turn to completion. harnessSessionId is the conversation so far — null on the first turn of a new one — so each turn resumes the last.

Parameter Type
content string
turn { harnessSessionId: string | null; outputSchema?: JsonSchema; signal: AbortSignal; }
turn.harnessSessionId string | null
turn.outputSchema? JsonSchema
turn.signal AbortSignal

AsyncIterable<SessionEvent>


Property Type
call PermissionRequest
expiresAt? string
id string
runId string
status "pending" | "cancelled" | "approved" | "denied" | "expired"

Property Type
error? boolean
id string
result unknown

Property Type
name string
sessionId? string

Property Modifier Type Description
guarantees readonly Guarantees Copied from the mode that started it — what this session has, not what a new one would.
harnessSessionId readonly string | null -
harnessVersion readonly string | null The harness build this session observed, when it could see one.
id readonly string -
mode readonly ModeId -
warnings? readonly readonly string[] What the adapter wants known about this session as it starts — the same notes a launch returns in LaunchPlan.warnings, such as native tools still reachable that Barry has equivalents for. Absent means none.

answer(request, decision): Promise<void>

Parameter Type
request PermissionRequest
decision PermissionDecision

Promise<void>

optional attach(): Promise<SessionAttachment>

Opens the session to a vendor TUI that renders it, where the harness’s TUI can attach to Barry’s engine. The engine stays up while anything is attached; each attach is undone by one detach.

Promise<SessionAttachment>

close(): Promise<void>

Promise<void>

optional compact(): Promise<void>

Compact the conversation so far, where the harness supports it. Optional: its presence is the capability. A harness that cannot compact (codex, cursor, opencode today) simply does not define it, and callers answer 501 rather than sending a literal /compact that lands as a user message.

Promise<void>

deliver(content, options?): Promise<DeliveryReceipt>

Parameter Type
content string
options? DeliveryOptions

Promise<DeliveryReceipt>

optional detach(): void

void

events(): AsyncIterable<SessionEvent>

Every event, across turns, each yielded once. A session has one reader; events that arrive while nobody is reading wait for the next one.

AsyncIterable<SessionEvent>

optional externalTurns(): AsyncIterable<SessionEvent>

Turns another client started, such as a person typing in an attached TUI, kept apart from events(), whose reader is waiting on Barry’s own turns. The person’s message arrives as a text with role user. Each turn ends with one done.

AsyncIterable<SessionEvent>

interrupt(): Promise<void>

Stop the running turn. Rejects with NotSupportedInMode where the mode cannot — resolving and doing nothing would read as “stopped” to every caller.

Promise<void>

status(): "error" | "idle" | "active"

"error" | "idle" | "active"


Where a vendor TUI attaches to render a hosted session.

Property Type Description
address string The engine’s address, as the TUI’s own client takes it.
harnessSessionId string The conversation the TUI resumes.

Property Type Description
allowedNativeTools? string[] -
cwd string -
decide? (request) => Promise<PermissionDecision> Rules on each native tool call the harness asks about. Absent means every such call is refused: a hosted session with no bound would otherwise run whatever the harness offers.
deniedTools? string[] Honoured only where the harness can deny natively; see HarnessCapabilities.toolDenial.
egressSandbox? EgressPolicy -
endpoint? Endpoint Set only when the model’s vendor is not the harness’s own: where to send requests instead, and with what key. Absent means the harness’s own settings.
env Record<string, string | undefined> -
ephemeral? boolean The session runs one piece of work and is never resumed, so the harness keeps no state past close — a structured run, not a conversation.
extraArgs? string[] Raw passthrough args the user typed after Barry’s own flags.
maxTurns? number -
mcpServers Record<string, McpServerConfig> -
model? `${string}/${string}` Absent means the harness picks its own model.
options? unknown Harness-specific settings, validated against Adapter.options.
pluginDirs? string[] Directories of skills and commands to mount, where the harness mounts plugins.
projectRoots? string[] Extra roots the agent may reach, under the harness’s own access rules.
resume? object -
resume.harnessSessionId? string -
resume.last? boolean -
resume.picker? boolean -
sessionId string Barry’s session id.
smallModel? `${string}/${string}` For the harness’s own cheap background calls, where it makes any.
strictMcpConfig? boolean False lets the harness also load MCP servers from its own config (--relax).
systemPrompt? string -
telemetryEndpoint? string Where Barry’s OTLP receiver listens. Passed in because where a bag service listens is a host fact an adapter must not look up.
telemetryHeaders? Record<string, string> Headers the receiver requires — its auth, which is the host’s to know.

Property Type
guarantees Guarantees
guaranteesUnverified boolean
harnessVersion? string

Property Type Description
data unknown -
harnessSessionId? string -
raw string The final text the payload was taken from.

Property Type Description
maxRetries? number Correction rounds after the first prompted attempt. Default 1.
prompt string -
schema JsonSchema -
signal? AbortSignal Stops the attempt in flight and the run; the run then rejects.
structuredOutput "native" | "prompted" From the session’s mode, overridden by the endpoint when a model is routed elsewhere.

start(): Promise<Session>

A FRESH session per attempt. Retries carry the previous output and its errors in the prompt rather than continuing a conversation, because not every harness can resume one, and a structured run must behave the same on all of them.

Promise<Session>


Property Type
store TurnExecutionStore

optional acquire(): Promise<{ release: void; }>

Promise<{ release: void; }>

authorize(sessionId, call): Promise<PermissionDecision>

Parameter Type
sessionId string
call PermissionRequest

Promise<PermissionDecision>

optional committed(sessionId, sequence): void

Notification is only a wake-up; the committed store is the replay source.

Parameter Type
sessionId string
sequence number

void

openHarness(sessionId): Promise<ContinuationHarness>

Parameter Type
sessionId string

Promise<ContinuationHarness>


admit(input): TurnSnapshot

Parameter Type
input { actor: string; content: unknown; ifActive?: "error" | "queue"; policy: { mode: "automatic"; } | { expiresAt?: string; mode: "review_required"; }; requestId: string; runId: string; sessionId: string; }
input.actor string
input.content unknown
input.ifActive? "error" | "queue"
input.policy { mode: "automatic"; } | { expiresAt?: string; mode: "review_required"; }
input.requestId string
input.runId string
input.sessionId string

TurnSnapshot

append(sessionId, turnId, event): number

Parameter Type
sessionId string
turnId string
event unknown

number

cancel(sessionId, turnId): TurnSnapshot

Parameter Type
sessionId string
turnId string

TurnSnapshot

claim(sessionId, turnId, owner): boolean

Parameter Type
sessionId string
turnId string
owner string

boolean

continuation(sessionId, turnId): ContinuationDescriptor

Parameter Type
sessionId string
turnId string

ContinuationDescriptor

conversation(sessionId): ContinuationDescriptor | undefined

Parameter Type
sessionId string

ContinuationDescriptor | undefined

decisions(sessionId, turnId): Map<string, PermissionDecision>

Parameter Type
sessionId string
turnId string

Map<string, PermissionDecision>

denied(sessionId, turnId, owner, call, outcome): RecordedCallResult

Parameter Type
sessionId string
turnId string
owner string
call PermissionRequest
outcome RecordedCallResult

RecordedCallResult

execute(sessionId, turnId, owner, call, effect): Promise<RecordedCallResult>

Parameter Type
sessionId string
turnId string
owner string
call PermissionRequest
effect () => Promise<RecordedCallResult>

Promise<RecordedCallResult>

finish(sessionId, turnId, owner, outcome): TurnSnapshot

Parameter Type
sessionId string
turnId string
owner string
outcome { conversation?: ContinuationDescriptor; error?: string; result?: unknown; state: "failed" | "completed" | "recovery_required"; }
outcome.conversation? ContinuationDescriptor
outcome.error? string
outcome.result? unknown
outcome.state "failed" | "completed" | "recovery_required"

TurnSnapshot

lost(sessionId, turnId, error): TurnSnapshot

Parameter Type
sessionId string
turnId string
error string

TurnSnapshot

pause(sessionId, turnId, owner, continuation, calls): TurnSnapshot

Parameter Type
sessionId string
turnId string
owner string
continuation ContinuationDescriptor
calls PermissionRequest[]

TurnSnapshot

optional promoteQueued(sessionId): { input: unknown; turn: TurnSnapshot; } | undefined

Parameter Type
sessionId string

{ input: unknown; turn: TurnSnapshot; } | undefined

recorded(sessionId, turnId, call): RecordedCallResult | undefined

Parameter Type
sessionId string
turnId string
call PermissionRequest

RecordedCallResult | undefined

released(sessionId, turnId, owner): void

Parameter Type
sessionId string
turnId string
owner string

void

resolve(input): TurnSnapshot

Parameter Type
input { actor: string; context?: unknown; decisions: ApprovalDecision[]; requestId: string; runId: string; sessionId: string; turnId: string; }
input.actor string
input.context? unknown
input.decisions ApprovalDecision[]
input.requestId string
input.runId string
input.sessionId string
input.turnId string

TurnSnapshot

snapshot(sessionId, turnId): TurnSnapshot

Parameter Type
sessionId string
turnId string

TurnSnapshot


Property Type
error? string
id string
interrupts PublicInterrupt[]
result? unknown
reviewPolicy { mode: "automatic"; } | { expiresAt?: string; mode: "review_required"; }
revision number
runId string
sessionId string
state TurnState

ApprovalContinuation = "durable" | "live" | "unsupported"


CallState = "not_started" | "executing" | "completed" | "failed" | "denied" | "uncertain"


McpServerConfig = { args?: string[]; command: string; env?: Record<string, string>; type?: "stdio"; } | { headers?: Record<string, string>; type: "http" | "sse"; url: string; }


PermissionDecision = { allow: true; persist?: boolean; } | { allow: false; reason?: string; }

{ allow: true; persist?: boolean; }

persist applies the answer to every later call of the same shape.


{ allow: false; reason?: string; }


ReviewPolicy = z.infer<typeof ReviewPolicySchema>


SegmentOutcome = { conversation?: ContinuationDescriptor; result?: unknown; type: "completed"; } | { error: string; type: "failed"; } | { calls: PermissionRequest[]; continuation: ContinuationDescriptor; type: "interrupted"; }


SessionEvent = object & { harnessSessionId: string; type: "init"; } | { role?: "assistant" | "user"; text: string; type: "text"; } | { text: string; type: "partial"; } | { id: string; input: unknown; tool: string; type: "tool_use"; } | { error?: boolean; id?: string; result: unknown; type: "tool_result"; } | { elapsedSeconds: number; id: string; tool: string; type: "tool_progress"; } | { description?: string; id: string; input: unknown; tool: string; type: "permission_request"; } | { status: "idle" | "active" | "error"; type: "status"; } | { error?: string; result?: string; structured?: unknown; type: "result"; } | { error: string; type: "error"; } | { id: string; type: "usage"; usage: TokenUsage; } | { durationMs?: number; turns?: number; type: "done"; usage?: TokenUsage; }

The one event vocabulary. Every turn ends with exactly one done, so a reader can wait for it without knowing how the harness ends a turn.

Name Type Description
parentToolUseId? string Set when a subagent, not the main thread, produced the event: the tool call that spawned it.

TurnState = "queued" | "running" | "waiting_for_input" | "recovery_required" | "completed" | "failed" | "cancelled"

const ReviewPolicySchema: ZodDiscriminatedUnion<[ZodObject<{ mode: ZodLiteral<"automatic">; }, $strict>, ZodObject<{ expiresAt: ZodOptional<ZodISODateTime>; mode: ZodLiteral<"review_required">; }, $strict>], "mode">

allowedNative(config, nativeTools, native?): string[]

The native tools a session may use (ADP-6): every adapter derived this the same way, so it lives here once. grantable restricts to a declared subset (pi); omit it to allow any requested native tool. inseparable groups drop whole when any member is unavailable. Denials are case-insensitive, matching the native policy and configureHarnessSession.

Parameter Type
config Pick<SessionConfig, "allowedNativeTools" | "deniedTools">
nativeTools readonly string[]
native? NativeControl

string[]


assertSessionOwner(session, identity): void

Parameter Type
session { identity_id?: number | null; } | undefined
identity number

void


canEnforceInSandbox(actions): boolean

Whether Barry’s egress proxy can fully enforce a network bound’s actions.

The proxy filters by host, not by HTTP method, so it cannot express “reads allowed, writes denied”. Partial denials fall back to the app-level guards; callers should say so rather than implying kernel-grade coverage.

Parameter Type
actions string[] | undefined

boolean


canonicalJson(value): string

Canonical JSON rejects values that would silently change across persistence.

Parameter Type
value unknown

string


configureHarnessSession(input, nativeTools, native?): SessionConfig

Apply the non-negotiable native ceiling before any adapter starts work.

Parameter Type
input SessionConfig
nativeTools readonly string[]
native? NativeControl

SessionConfig


configureSession(input): SessionConfig

Every interface supplies the same effective harness configuration. Own mutable collections.

Parameter Type
input SessionConfig

SessionConfig


declareSession(mode, observedVersion?): SessionDeclaration

An unknown build is not a mismatch: not every harness reports one, and marking every such session unverified would make the flag meaningless.

Parameter Type
mode Mode
observedVersion? string

SessionDeclaration


disallowedTools(config, nativeTools, native?): string[]

The native tools a session must refuse: the complement of allowedNative over the adapter’s table, plus the caller’s explicit denials (ADP-6).

Parameter Type
config Pick<SessionConfig, "allowedNativeTools" | "deniedTools">
nativeTools readonly string[]
native? NativeControl

string[]


executionHash(value): string

Parameter Type
value unknown

string


extractFence(text, label): string | null

Extract labeled fences, preferring four backticks and respecting JSON strings when balancing three-backtick payloads.

Parameter Type
text string
label string

string | null


isScopedMcpTool(tool, servers): boolean

Vendor spellings for a tool on an explicitly configured MCP server.

Parameter Type
tool string
servers readonly string[]

boolean


perTurnSession(options): Session

Parameter Type
options PerTurnOptions

Session


refuseDeniedTools(deniedTools?): (request) => Promise<PermissionDecision>

The ruling for a session whose only per-call policy is its denied tools: a tool denied by name is refused, and everything else runs — what the session got before its harness asked. A hosted session given no ruling refuses every call, so a caller with nothing to deny still passes this.

Parameter Type Default value
deniedTools readonly string[] []

(request) => Promise<PermissionDecision>


runStructured(run): Promise<StructuredReply>

Parameter Type
run StructuredRun

Promise<StructuredReply>


structuredOutputFor(mode, route): "native" | "prompted"

Who enforces a structured run’s schema. The endpoint a model is routed to has the final say when the model is another vendor’s: a compatible API can accept a schema field and ignore it, which is measured per endpoint. Else the hosted mode does.

Parameter Type
mode { structuredOutput: "native" | "prompted"; }
mode.structuredOutput "native" | "prompted"
route { harnessVendor: string | undefined; model: `${string}/${string}` | undefined; models: Pick<Models, "endpoint">; }
route.harnessVendor string | undefined
route.model `${string}/${string}` | undefined
route.models Pick<Models, "endpoint">

"native" | "prompted"