Live Ingress
Live ingress is how a JacqOS app accepts real input without giving up replay. HTTP clients, chat sessions, webhooks, local scripts, and Studio all use the same contract:
append observations -> run the lineage -> subscribe to eventsThere is no separate chat runtime or webhook runtime. Adapters append observations, JacqOS derives facts and intents from the ontology, effect authority decides whether effects may execute, and the event stream publishes durable projections you can resume.
Start The Local Runtime
Section titled “Start The Local Runtime”Run serve from a JacqOS app directory:
jacqos serve --port 8787 --jsonThe default bind address is loopback. Binding outside loopback requires both
--allow-non-loopback and --auth-token-env; unauthenticated non-loopback
serve is rejected. The JSON receipt includes the listen address, auth state,
inspection metadata, and the retention stance for observations, run records,
attempt reports, idempotency rows, and durable SSE events.
The Core Loop
Section titled “The Core Loop”A live producer can use the generic endpoints directly:
POST /v1/lineages/live-demo/observationsPOST /v1/lineages/live-demo/runGET /v1/lineages/live-demo/events?since=head:0POST /observations appends one immutable observation. POST /observation-batches appends ordered JSONL or an ordered array. Both surfaces
accept idempotency fields so a retry can return the original append receipt
instead of duplicating evidence.
POST /run evaluates one lineage. Use shadow to evaluate without effects,
prefer_committed_activation to execute only when the loaded package matches
the committed activation, and require_committed_activation when a mismatch
must fail instead of falling back to shadow.
The event stream is Server-Sent Events:
GET /v1/lineages/live-demo/events?since_event=12GET /v1/lineages/live-demo/events?since=head:42&relation=agent.alertGET /v1/lineages/live-demo/events?event_type=reconciliation.requiredUse Last-Event-ID or since_event to resume. Use relation when one
subscriber owns one derived relation, and event_type when it needs a lifecycle
event such as fact.delta, intent.admitted, effect.succeeded,
reconciliation.required, or run.completed.
If the client falls behind a bounded catch-up request, JacqOS emits
stream.backpressure and closes the stream. If a future retention policy ever
removes the requested window, JacqOS emits stream.resume_window_exceeded and
the client must recover from the query endpoints.
Query Before You Subscribe
Section titled “Query Before You Subscribe”Live clients should catch up from query endpoints before opening or resuming a stream:
| Surface | Endpoint |
|---|---|
| Lineage status | GET /v1/lineages/{lineage_id}/status |
| Observation tail | GET /v1/lineages/{lineage_id}/observations?from_head=N |
| Fact deltas | GET /v1/lineages/{lineage_id}/facts?from_head=N&to_head=M |
| Intent deltas | GET /v1/lineages/{lineage_id}/intents?from_head=N&to_head=M |
| Effects | GET /v1/lineages/{lineage_id}/effects |
| Runs | GET /v1/lineages/{lineage_id}/runs |
| Provenance | GET /v1/lineages/{lineage_id}/provenance?fact_id=... |
Facts, intents, and effects are evaluator-scoped. If the request omits
evaluator_digest, JacqOS uses the committed activation for the lineage, then
falls back to the latest run. If neither exists, the query returns
evaluator.unavailable instead of guessing.
Chat Adapter
Section titled “Chat Adapter”The chat adapter is a thin wrapper over append, run, and subscribe:
POST /v1/adapters/chat/sessions/{session_id}/messages{ "message_id": "msg-1", "text": "Can you check my order?", "once": true, "effect_mode": "shadow"}The adapter writes chat.user_message to lineage chat:{session_id}. It
auto-creates only that chat: lineage prefix, uses
chat:{session_id}:{message_id} as the default idempotency key, runs the
lineage, and returns:
- the observation receipt,
- the
run_id, - an
events_urlfiltered to acceptedchat.assistant_messagefacts, - accepted assistant-message projections, each with a
provenance_url.
Your ontology still decides what an assistant message means. A model or parser
may produce candidate or proposal facts, but only a domain rule should derive
the accepted chat.assistant_message relation that the adapter returns.
Webhook Adapter
Section titled “Webhook Adapter”The webhook adapter is for non-chat producers that need signature validation and delivery idempotency before append:
POST /v1/adapters/webhooks/{adapter_id}/deliveries{ "lineage_key": "account-42", "delivery_id": "evt-1001", "kind": "webhook.delivery", "payload": { "account_id": "account-42", "event_type": "invoice.paid" }, "signature": "sha256:...", "secret_env": "JACQOS_WEBHOOK_SECRET", "once": true, "effect_mode": "shadow"}The adapter validates the signature before appending anything. The current V1
local signature shape is sha256(secret + "." + canonical_signed_payload),
where the signed payload contains adapter_id, delivery_id, kind, and
payload. If the signature fails, JacqOS returns webhook.signature_invalid
and the observation log is unchanged.
Valid deliveries append to lineage webhook:{adapter_id}:{lineage_key}. The
default idempotency key is webhook:{adapter_id}:{delivery_id}. The receipt
returns the observation address, idempotency digest, run_id, events_url,
and run receipt.
Studio Live Mode
Section titled “Studio Live Mode”Studio can connect to serve instead of reading a stale local snapshot:
export JACQOS_STUDIO_SERVE_URL=http://127.0.0.1:8787export JACQOS_STUDIO_LINEAGE=live-demojacqos-studioIf serve requires auth, also set:
export JACQOS_STUDIO_SERVE_TOKEN="$JACQOS_SERVE_TOKEN"In serve mode, Studio reads the public query and event surfaces: lineage status, observation tail, fact and intent deltas, effects, run records, provenance, contradiction/invariant evidence from attempt reports, and reconciliation-required events. It does not introduce a second live truth path.
Multi-Agent Live Pattern
Section titled “Multi-Agent Live Pattern”Use one lineage when independent producers need shared reality. Each producer appends observations in its own vocabulary. The ontology derives shared facts. Subscribers filter the event stream by the relation they own:
GET /v1/lineages/live-demo/events?since=head:0&relation=subscriber.risk_queueGET /v1/lineages/live-demo/events?since=head:0&relation=subscriber.support_queueThe bundled Multi-Agent Live example
demonstrates this pattern. A risk producer and support producer append
independent observations. The ontology derives shared.review_required, emits
relation-specific subscriber facts, and uses an observed dispatch receipt to
retract the dispatch intent so the subscriber does not loop.
Replay Still Owns The Proof
Section titled “Replay Still Owns The Proof”A live run is not special evidence. It is an observation history plus durable operational projections. To prove a live path, capture the same observation sequence as JSONL and replay it:
jacqos observe --jsonl fixtures/shared-reality.jsonl --lineage live-demo --create-lineage --jsonjacqos run --lineage live-demo --once --shadow --jsonjacqos replay fixtures/shared-reality.jsonljacqos verifyThe replay proof should not depend on run_id values, SSE event ids, or local
adapter process state. Those are operational handles. Observations, facts,
intents, effects, provenance, and fixtures remain the contract you review.
Next Steps
Section titled “Next Steps”- CLI Reference lists every serve endpoint and error code.
- How JacqOS Runs Agents explains the observation-evaluation-effect loop behind serve.
- Effects and Intents explains effect authority and reconciliation.
- Replay and Verification shows how to turn live histories into fixture proofs.
- Multi-Agent Patterns explains shared-reality coordination.
- Studio Cloud Onboarding shows how to publish a verified app to a secured hosted endpoint.