Skip to content

Gateway + personal agent

Spacecraft is not only for embedded harnesses (procurement, legal, productized agents). It also targets a gateway + personal agent profile: an always-on or on-demand assistant bound to you (or your household / team), receiving signals from chat, email, or webhooks and replying through the same harness model.

The comm_array subsystem (Telegram first) demonstrates the pattern: the orchestrator ignites a channel adapter, listens for inbound messages, maps each message to a MissionSignal, and runs the mission loop with activeSignal bound so the agent knows how to respond.

That is a minimal gateway: one inbound channel, one blueprint, long-lived process.

Repo ADRs define the generalization:

  • ADR 026GatewayPort abstraction; personal-agent security and vault posture; scheduling owned by Starflow, not reimplemented in Spacecraft.
  • ADR 029 — example verticals (feeds, nightly knowledge graph, email brief) and the Starflow ↔ Spacecraft seam.
ConcernOwner
Cron, webhooks, “run this harness every morning”Starflow Designer
Durable checkpoints, wait / resumeWait, run auditStarflow Engine
Model, memory, tools, blueprint graphSpacecraft

Typical pattern: a Starflow pipeline step runs sc launch … (or the HTTP equivalent) with inputs produced by an earlier fetch/normalize step.

It is normal for Spacecraft to run an internal agent loop while Starflow runs the outer workflow. The boundary is:

  • Spacecraft can reuse the same primitive style (nodes/edges/ReAct-like loops) for an agent episode.
  • Starflow remains the only owner of durable orchestration semantics (wait / resumeWait, checkpoint replay, trigger scheduling).

So this is usually not a circular dependency problem; it is a scope boundary problem. Keep episode cognition in Spacecraft and durable workflow truth in Starflow.

CapabilityOwner
ReAct loop, prompt/context flow, tool choiceSpacecraft
Durable HITL gates (approval pauses that survive restarts)Starflow Engine (wait / resume)
Long research jobs and async fan-out/fan-inStarflow Engine
Background long-term memory indexing jobsStarflow Engine (scheduled/event-driven)
In-turn memory retrieval for a replySpacecraft

For a full-fledged chat agent, the common pattern is:

  1. Spacecraft handles the foreground turn loop (quick cognition + tool use + reply).
  2. Spacecraft emits work for anything durable/long-running.
  3. Starflow runs those async branches and resumes via callbacks/events.

That matches industry practice in modern agent stacks: a fast online agent runtime plus a durable orchestration runtime for long-lived work.

Mental model: the agent runtime (Spacecraft) contains the ReAct loop for each episode; Starflow wraps episodes with durable workflow semantics when needed.

sequenceDiagram
autonumber
participant User
participant Spacecraft as Spacecraft (foreground episode)
participant Starflow as Starflow Engine (durable branch)
participant Human as Human approver
User->>Spacecraft: chat turn
Spacecraft->>Spacecraft: ReAct loop + in-turn memory retrieval
Spacecraft-->>User: immediate response
alt approval needed
Spacecraft->>Starflow: enqueue approval task
Starflow->>Starflow: wait(human)
Human->>Starflow: approve/reject
Starflow-->>Spacecraft: callback event
end
alt long research needed
Spacecraft->>Starflow: enqueue async research workflow
Starflow->>Starflow: retries + joins
Starflow-->>Spacecraft: research artifact refs
end

For both chat assistants and coding agents, the common architecture is:

  • a fast online agent runtime for the current turn (prompt loop, tool calls, immediate reply),
  • plus a durable orchestration runtime for waits, approvals, long jobs, and replayable audit.

That is exactly the Starflow + Spacecraft seam: Spacecraft contains the episode loop; Starflow wraps episodes when durability is required.

When Spacecraft needs durable async work, emit a small envelope to Starflow:

FieldRequired
contractVersion ("sc-sf-task/v0")yes
taskTypeyes
idempotencyKeyyes
correlationIdyes
spacecraftRunIdyes
turnIdyes
replyChannel (mode, target, authRef, expects)yes
payloadRef (preferred) or small payloadyes (one of)

Starflow callbacks should return task.result/v0 with the same idempotencyKey + correlationId and a terminal status (succeeded, failed, cancelled, timed_out).

  • Starflow dedupes by idempotencyKey.
  • Retries preserve idempotencyKey and correlationId.
  • Spacecraft treats duplicate callbacks as no-op-safe.
  • Zod (source of truth): packages/starflow-core/src/schema/sc-sf-task-contract.ts — use safeParseSpacecraftToStarflowTaskEnvelope / safeParseTaskResultEnvelope and assertMatchingTaskResult anywhere both sides meet JSON over the wire.
  • JSON Schema (tooling): getScSfTaskEnvelopeJsonSchema() and getTaskResultEnvelopeJsonSchema() in packages/starflow-core/src/schema/json-schema-export.ts.
  • Starflow: POST /webhooks/spacecraft-tasks validates an sc-sf-task/v0 body at the server boundary (optional bearer token when STARFLOW_TRIGGER_TOKEN is configured).
  • Spacecraft HTTP gateway: POST …/task-result on the same base path as chat ingress (e.g. /ingress/task-result) validates task.result/v0; optional header X-Spacecraft-Sc-Sf-Task supplies the original task JSON for correlation checks before the orchestrator sees the signal.