Skip to content

Agent spawning: create scoped agents with distinct harnesses#35

Merged
Jacobobber merged 1 commit into
mainfrom
feat/agent-spawning
Jul 8, 2026
Merged

Agent spawning: create scoped agents with distinct harnesses#35
Jacobobber merged 1 commit into
mainfrom
feat/agent-spawning

Conversation

@Jacobobber

Copy link
Copy Markdown
Owner

The orchestrator can now create agents, not just dispatch to ones that already exist, each with a different harness and a different task, all coordinating over the channels. And the reason to build it on hallpass:

Each spawned agent is a scoped identity, not a trusted one.

Team.spawn mints each agent a token carrying only its harness scopes, then launches it through a pluggable Spawner, passing the identity, task, and channel by environment:

_, mint = dev_app()   # or your IdP's client-credentials flow in production
team = Team(mint=lambda name, scopes: mint(name, scopes),
            spawner=SubprocessSpawner(["python", "agent.py"]), channel="work")

team.spawn(AgentSpec("reviewer",  scopes=frozenset({"github:read"}), task="review PR 42"))
team.spawn(AgentSpec("messenger", scopes=frozenset({"slack:write"}), task="post to #eng"))
# inside agent.py
ctx = AgentContext.from_env()   # ctx.name, ctx.token (scoped), ctx.task, ctx.channel
  • The reviewer's token carries github:read and nothing else; the messenger's carries slack:write and nothing else. A confused or compromised agent can only reach the tools its harness grants, enforced at call time and audited. Isolation between agents is the auth layer.
  • hallpass stays model-agnostic: it provisions the identity and harness and launches the process; what thinks inside is yours. SubprocessSpawner is the default; swap it for any Spawner.
  • Team tracks handles (alive / shutdown).

7 new tests: AgentContext.from_env round-trip + missing-env, Team.spawn mints a scope-limited token and builds the env, different agents get different harnesses, alive/shutdown, and two real-subprocess tests (env passing end to end, and lifecycle/terminate). Runnable two-process demo: examples/spawn_agents.py + examples/spawned_agent.py. Additive over 1.x. 268 tests, mypy --strict, ruff (whole repo), catalog-freshness green. v1.2.0.

The orchestrator can now spawn agents, not just dispatch to ones that exist.
Each spawned agent is a scoped identity, not a trusted one -- its token carries
only its harness scopes, so a reviewer reaches GitHub and nothing else.

- AgentSpec (name, harness scopes, task); Team.spawn mints the scoped token and
  launches the agent through a pluggable Spawner, passing name/token/task/
  channel by environment. AgentContext.from_env() picks it up inside the process.
- Default SubprocessSpawner runs a fixed command per agent; swap it for any
  Spawner. hallpass stays model-agnostic -- the loop inside the process is yours.
- Team tracks handles (alive/shutdown). Demos: examples/spawn_agents.py +
  spawned_agent.py (two real subprocess agents coordinating over one channel).

Additive. 268 tests (+7, incl. real-subprocess env-passing + lifecycle),
mypy --strict, ruff (whole repo), catalog freshness all green. v1.2.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Jacobobber Jacobobber merged commit 754eec0 into main Jul 8, 2026
12 checks passed
@Jacobobber Jacobobber deleted the feat/agent-spawning branch July 8, 2026 19:34
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