Skip to content

Multi-Agent Live Walkthrough

examples/jacqos-multi-agent-live/ is the smallest live multi-agent shape in the repository. A risk producer and a support producer append independent observations to one lineage. JacqOS derives a shared review state, emits relation-specific subscriber facts, and uses an observed dispatch receipt to stop the subscriber from looping.

The proof is not that two scripts can send messages. The proof is that no agent-to-agent message carries truth. Every subscriber sees facts derived from the same observation history.

jacqos-multi-agent-live/
jacqos.toml
ontology/
schema.dh
rules.dh
mappings/
inbound.rhai
fixtures/
shared-reality.jsonl
shared-reality.expected.json
scripts/
live-demo.sh

The observation kinds are deliberately plain:

ProducerObservation kindPurpose
Riskrisk.signalReports a risk score for an account.
Supportsupport.messageReports customer support context for the same account.
Subscriberagent.review_dispatchedRecords that the derived review was dispatched.

The ontology derives shared.review_required only when the independent producer facts agree. It then derives subscriber.risk_queue and subscriber.support_queue as relation-specific read models for subscribers.

From the example directory:

Terminal window
jacqos replay fixtures/shared-reality.jsonl
jacqos verify

The expected fixture proves:

  • both producer observations are preserved,
  • shared.review_required is derived from both producer facts,
  • each subscriber relation receives the same review id,
  • intent.dispatch_review is retracted after the dispatch receipt,
  • agent.loop_blocked explains why the subscriber does not fire again.

The same JSONL can drive a live lineage:

Terminal window
jacqos observe --jsonl fixtures/shared-reality.jsonl --lineage live-demo --create-lineage --json
jacqos run --lineage live-demo --once --shadow --json
jacqos serve --port 8787

Subscribers can catch up by relation:

GET /v1/lineages/live-demo/events?since=head:0&relation=subscriber.risk_queue
GET /v1/lineages/live-demo/events?since=head:0&relation=subscriber.support_queue

Both subscribers are reading the same lineage event projection. The relation filter only narrows what they see; it does not create separate state.

Connect Studio to the serve process:

Terminal window
export JACQOS_STUDIO_SERVE_URL=http://127.0.0.1:8787
export JACQOS_STUDIO_LINEAGE=live-demo
jacqos-studio

Use Studio to inspect the observation tail, fact deltas, intent lifecycle, effect audit, and provenance for the shared review. The useful debugging question is always the same: which observations and rules made this subscriber fact true?

  • Put independent producer evidence in observations, not in agent memory.
  • Derive shared state in ontology rules, not in a message handler.
  • Give each subscriber a relation it owns and subscribe with ?relation=....
  • Record dispatch receipts as observations so replay can explain loop safety.
  • Keep a fixture that proves the live path without depending on run_id or SSE event_id values.