Skip to content

Add reference agent runners (run_worker / serve_queue)#42

Merged
Jacobobber merged 1 commit into
mainfrom
feat/reference-runner
Jul 8, 2026
Merged

Add reference agent runners (run_worker / serve_queue)#42
Jacobobber merged 1 commit into
mainfrom
feat/reference-runner

Conversation

@Jacobobber

Copy link
Copy Markdown
Owner

Reference agent runners (run_worker / serve_queue)

The reusable worker loop a served agent runs — shipped once instead of rewritten per agent. hallpass provisions the identity, scope, channel, and durable queue, but it runs no model loop of its own (that's deliberate). What a spawned agent still needs is the loop around its work — claim/receive, run, report, heartbeat, stop — and that loop is the same whichever model (or none) sits inside a handler.

  • serve_queue(queue, worker, handlers, …) — claims one task from a TaskQueue per pass, dispatches to handlers[task.do], and completes it. The handler's returned mapping becomes the result fields (ok=True); an unknown operation completes ok=False note "no handler"; a raising handler completes ok=False with only the exception type as the note, never its message (mirrors the orchestrator Worker). Idempotent + lease-safe, so an expired-lease re-run can't overwrite a recorded result.
  • run_worker(worker, …) — the same loop over an A2A Worker/channel.

Both take:

  • stop predicate and/or max_idle_roundsserve-forever or drain-and-return (neither set ⇒ drain once and return, never a busy-spin).
  • an injectable sleep — the loops test without wall-clock waits.
  • a heartbeat hook — wire bus.announce into it to hold a live-roster seat, tying serving and presence (v1.7) together.

The auth boundary is unchanged: a handler acts with the agent's scoped token. The handler is exactly where a model or tool call would go.

Verification

  • tests/test_runner.py — 10 tests: drain-and-return with no termination, stop predicate, max_idle_rounds ends an idle loop (with the right sleep count), heartbeat called each pass, heartbeat holding a roster seat; queue: completes tasks, unknown-op clean fail, handler error reports type only (message not leaked), stop leaves the backlog for another worker, drain-then-return.
  • examples/reference_agent.py runs and prints completed 3 tasks; roster now ['resizer-1'].
  • Full suite 320 passed (+10). mypy --strict, ruff, catalog freshness all green.

Additive. Rounds out the coordination layer (spawn → route → queue → serve), all on the one auth core.

The reusable worker loop a served agent runs, shipped once instead of
rewritten per agent. hallpass runs no model loop of its own; what a spawned
agent still needs is the loop around its work, and that loop is model-agnostic:

- serve_queue(queue, worker, handlers, ...) claims from a TaskQueue, dispatches
  by operation to a handler, and completes each task -- idempotent and
  lease-safe. A raising handler completes ok=False with only the exception
  type (never its message), mirroring the orchestrator Worker; an unknown op
  completes ok=False note 'no handler'.
- run_worker(worker, ...) is the same loop over an A2A Worker/channel.
- Both take stop / max_idle_rounds (serve-forever or drain-and-return), an
  injectable sleep (loops test without wall-clock waits), and a heartbeat hook
  -- wire bus.announce into it to hold a live-roster seat, tying serving and
  presence together. The handler acts with the agent's scoped token; the auth
  boundary is unchanged. Demo: examples/reference_agent.py.

320 tests (+10), mypy --strict, ruff, catalog freshness green. v1.9.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Jacobobber Jacobobber merged commit 24c3e93 into main Jul 8, 2026
12 checks passed
@Jacobobber Jacobobber deleted the feat/reference-runner branch July 8, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant