Agent Coordinator Boundary

SciDEX should dispatch scientific judgment through agent containers, not through substrate-internal prompt runners. The coordinator contract is the agent-owned surface for that

Source: docs/agent-coordinator.md

Agent Coordinator Boundary

SciDEX should dispatch scientific judgment through agent containers, not through substrate-internal prompt runners. The coordinator contract is the agent-owned surface for that dispatch.

Ownership

  • scidex-substrate owns durable facts: agent_work_packet artifacts, schemas, lifecycle state, auth, links, rankings, bounties, signals, events, and verb APIs.

  • scidex-agents owns agent behavior: persona context, skill selection, provider/runtime choice, budget policy, artifact authoring, review routing, and container execution.

  • Prism reads substrate state and logs. It should not need to know whether a packet was acted on by Operon, Claude, Codex, Rosalind, or another harness.

Dispatch Modes

The same request shape supports two execution modes:

  • queued: publish or reuse an agent_work_packet and let eligible runtime containers claim it based on assignee, skills, budget, priority, and current context.

  • synchronous: hand a bounded request to a selected agent container and return when the container either writes deliverable refs through substrate APIs or records a blocked/failure state.

Substrate code should not import persona_runner, prompt builders, provider SDKs, or agent skills to satisfy these modes. It can create packets through scidex.create, update packet state through lifecycle verbs, or call a future agent-coordinator HTTP endpoint using this request envelope.

Python Contract

scidex_agents.coordinator exposes the stable dictionary payloads used by operator tools and future services:

from scidex_agents.coordinator import coordinator_request_from_packet

request = coordinator_request_from_packet(
    packet,
    run_id="work-selection-20260523T000000Z",
    mode="queued",
)

The helper returns ordinary dictionaries and dataclasses only. It has no substrate Python imports, no database access, and no provider SDK dependency. Work-selection publication uses the same module to create first-class agent_work_packet payloads and the temporary open_question fallback.

The same contract can normalize substrate API responses back into runnable requests:

from scidex_agents.coordinator import coordinator_request_from_artifact

request = coordinator_request_from_artifact(
    artifact,  # agent_work_packet or open_question fallback dict from substrate
    mode="synchronous",
    timeout_seconds=120,
)

This is the handoff point for claim/review/improvement loops: substrate owns packet lifecycle and ranking, while the agent runtime chooses whether to accept the packet, which skills to load, and how much compute to spend before writing deliverable refs back through substrate verbs.

Implemented Dispatch

The first implemented coordinator dispatch surface is queued dispatch into a selected runtime’s state directory:

from scidex_agents.coordinator import dispatch_coordinator_request

result = dispatch_coordinator_request(
    request.to_dict(),
    state_root="/home/ubuntu/scidex-agents/state",
)

For mode="queued", this writes or replaces the packet in state/<assigned_runtime>/work-selection.json using the same runtime-visible packet shape as runtimectl review work-selection --write-runtime-state. Replacement is keyed by packet_id, so retries are idempotent and do not duplicate work.

The equivalent local CLI accepts the JSON envelope on stdin:

python tools/scidex_agent_coordinator.py \
  --state-root /home/ubuntu/scidex-agents/state < envelope.json

mode="synchronous" is intentionally explicit rather than fake: the dispatch result returns status="synchronous_dispatch_not_implemented". The follow-up executor must run a selected container, collect deliverable refs, usage, and workspace evidence, then update the packet through substrate APIs.

Lifecycle Updates

Agent runtimes update first-class agent_work_packet artifacts through normal substrate optimistic-lock updates. The coordinator package provides payload helpers for the lifecycle states substrate already validates:

from scidex_agents.coordinator import deliver_work_packet_update_payload

payload = deliver_work_packet_update_payload(
    artifact,  # read from substrate, includes content_hash
    actor_ref="persona:kyle",
    deliverable_refs=["hypothesis:h-2"],
    result_summary="Published a reviewed hypothesis draft.",
)

The helper returns a scidex.update payload with type, id, patch, base_content_hash, and an idempotency key. It never writes directly. Agents should read the packet, reason about the next state, send the update through substrate, and retry on version conflict after re-reading current state.

Migration Rule

When a substrate worker or verb needs judgment, it should:

  1. detect the deterministic condition cheaply;

  2. create or update an agent_work_packet with input refs and acceptance criteria;

  3. let the agent coordinator choose claim timing, runtime, skills, and budget;

  4. require deliverables to be durable SciDEX refs before marking work complete.

This keeps substrate as the fabric and agents as the evolving scientific loop.