Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The spt api surface

The imperative half of the harness contract: the inbound entry points a harness’s hooks (and a shell’s binary) fire to keep spt-core’s on-disk state in sync. This page is the complete command reference plus the two startup flows that tie it together.

Two rules apply to every api call:

  1. --adapter <name> is mandatory. Every machinery invocation names the calling adapter — that’s what keeps a multi-harness node unambiguous.
  2. Prove association. Commands that touch an existing perch take --session-id <id> (matching the perch’s record) or a capability --token; shell commands authenticate with --link <token> (the link token minted at launch is the credential — no token, no access).
spt api --adapter <name> [--manifest <path>] <command> …

--manifest points at the adapter’s manifest for the commands that need it (e.g. capability).

The two startup flows

Harness-hosted — the harness owns the process; spt-core is invoked from inside it (hooks):

SessionStart hook ──► api seed --pid {parent_pid} --session-id {session_id}
session's listener ──► api listen <id>      (consumes the seed, holds the perch)

seed records an ephemeral hand-off keyed by parent pid; listen consumes it, registers the perch, drains backlog, and blocks relaying events into the session.

spt-hosted — spt-core spawns the session itself from the manifest’s [session.self] template, in its own terminal layer:

spt-core spawns the template ──► session comes up
session (or its wrapper) ──► api bind <id> --set-session-id <discovered-id>

No seed file is involved; bind attaches the live session to its perch post-spawn.

Session lifecycle

api seed --pid <pid> --session-id <id>

Harness-hosted startup, step 1: record an ephemeral seed keyed by the parent process id. Fired by the harness’s session-start hook. Prints SEEDED:<pid>.

api listen <id> [--once] [--parent-pid <pid>] [--subnet <name>]

Harness-hosted startup, step 2: consume the seed, register/hold the perch, drain spooled backlog, then block relaying messages. --once runs a single drain+receive cycle (testing). --subnet names the home subnet when this creates a brand-new endpoint on a multi-subnet node (home is assigned at creation; spt-core never guesses).

api bind <id> [--set-session-id <sid>]

spt-hosted startup: bind a freshly spawned session to its perch, recording the session id discovered post-spawn. Identity precedes sessions — rebinding never mints a new endpoint.

api boundary <clear|compact> <id> --to-session-id <sid>

The session was reset (context cleared or compacted) and continues under a new session id: rebind the perch, preserving the endpoint’s identity, spool, and history across the boundary.

api session-end <id> [--erase]

Soft teardown: the session is over; the perch’s spool and history are preserved (that’s what makes the next poll/listen drain work). --erase hard-wipes instead — the exception, not the rule.

api shutdown <id>

Graceful live-agent signoff: runs the final echo-commune before teardown (the context delta is never lost to ordering), then soft-stops. This is what the spt shutdown lifecycle path calls.

Activity and presence

api state <busy|idle> <id> [--no-gate]

Report the session’s activity state. Activity/idleness comes from these explicit reports — never from terminal quiescence, which lies. Reporting idle also arms the echo gate (below) unless --no-gate.

api echo-gate <set|clear> <id>

Manage the echo-gate sentinel directly. The gate marks “a summarization may be needed when this session ends without a graceful signoff” — state idle sets it as a side effect; a graceful signoff clears it.

api presence <id>

Report user/agent presence at this endpoint (feeds most-recently-active resolution across the subnet).

api driven-by <id>

Print which node (if any) is currently remote-driving this endpoint, so a session can tell whether input is local or remote.

Messages

Drain delivered messages over the hook channel (the pull-based path for harnesses whose hooks can’t inject). Deferred-flagged rows are excluded unless --include-deferred. With --link this is the shell-flavored drain: the link token authenticates, and the rows are the shell’s stamped command/text/file frames.

api history-log <id>

Append normalized history (body on stdin) to the endpoint’s native history store — the push half of [history] strategy = "native".

Workers

Nested, short-lived agents under a parent endpoint:

  • api worker-start <parent> <id> — create a nested worker perch.
  • api worker-poll <id> — drain the worker’s messages.
  • api worker-stop <id> — tear the worker perch down.

Shells

The driven-surface flavor of the contract. The link token minted at launch is the only credential a shell binary ever holds or needs:

The shell binary’s first call: resolve the instance by link token alone (the spawn template carries only {link_token}; the owner is derived from the link) and flip it online.

Push a sensory payload (one of the manifest’s declared [shell.sensory] types) to the owner’s live session. REST-only by definition: never spooled — if the owner isn’t live, it’s dropped with a diagnostic. Sensors report the present, not the past.

A shell suspends its linked owner directly (e.g. a power-button surface), bypassing agent messaging. Gated by the manifest’s can_shutdown pre-consent flag — fail-closed; an undeclared shell gets a refusal. The firing shell cascades offline with its siblings, by design.

Introspection

api capability

Print the adapter’s declared hostable_types (requires --manifest). The cheap way to smoke-test that spt-core reads your manifest the way you meant it.

Conventions

  • Output is line-oriented and stable: SEEDED:<pid>, READY:<id>, SENT:<id>, QUEUED:<id>, error lines as CODE:detail. Parse lines, not prose.
  • Exit codes: 0 success; non-zero = refused or failed, with the reason on stderr.
  • Commune/signoff are file-drops, not api commands. An agent writes <endpoint_id>-commune.md / <endpoint_id>-signoff.md into the manifest’s watched directory; spt-core’s watcher ingests it. There is deliberately no api commune.