This repository was archived by the owner on Aug 10, 2026. It is now read-only.
feat(agent): dual-discovery — register agents from #agent/thread alongside #agent/definition (rc.22) - #178
Merged
Merged
Conversation
…gside #agent/definition (rc.22)
Phase 4a of the threads-roles-context flatten. The daemon now discovers agents
from `#agent/thread` notes ALONGSIDE `#agent/definition`, so the def can later be
deleted. ADDITIVE + SAFE — in the default `both` mode the def path is untouched and
every currently-registered agent registers exactly as today (threads dedup against
defs; def wins on a name collision).
- `parseThreadSpec(threadNote) → AgentSpec` (pure): name = metadata.agent; backend/
model/mode/definition + sandbox knobs from thread metadata (safe defaults when
absent); systemPrompt EMPTY (identity composes from roles①+thread-content②+loadout③
at turn time — the body is the rolling summary, never the prompt). Shares the field
validators with parseAgentDef (extracted parseBackendField/parseModeField/
parseModelField/parseSandboxKnobs — behavior-preserving refactor).
- `DefVaultClient.listThreadNotes()` — queries the exact `#agent/thread` tag,
include_content unset (body isn't the prompt).
- Dual-list + register in loadAll, deduped by name (defs first → threads dedup; DEF
WINS in `both`). `reload` (def) + new `reloadThread` (thread) cover the reactive
path; both mode-gated. New `POST /api/vault/agent-thread` webhook + a thread-watch
CREATE trigger (create-only — per-turn upserts would churn; edits converge via the
60s poll).
- `agent_status` (metadata.agent_status, default enabled) — the enable/disable axis,
DISTINCT from metadata.status (the turn outcome). Discovery SKIPS a `disabled`
thread so a retired agent isn't re-registered from its thread.
- Discovery toggle `PARACHUTE_AGENT_DISCOVERY` = both(default)|thread|def — the cutover
is a flag-flip + restart, not a new PR. `thread` proves thread-discovery in isolation
before deleting defs; `def` is the escape hatch.
- Observability: `source: "def"|"thread"` on the agent listing + a per-agent boot log
line ("instantiated X from def/thread … source=…").
- Routing UNCHANGED. Thread-discovery is purely additive (never tears down via the
poll — teardown stays on the def-set diff + thread-status webhook + reloadThread).
No status stamp / no grant registration for thread-sourced agents (only #agent/role
carries capability).
Tests: parseThreadSpec, listThreadNotes, dual-discovery dedupe, agent_status skip,
the live shape (empty def body + thread → one agent), the toggle, reloadThread mode-
gating + deleted-teardown, reactive-ordering (def evicts a thread registered first),
the agent-thread webhook. Full suite 1413 pass / 0 fail; typecheck clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HAzWsgiJy4ndsWSCWY5S
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 4a of the threads-roles-context flatten (committed-core). The daemon now discovers agents from
#agent/threadnotes alongside#agent/definition, so the def can later be deleted. ADDITIVE + SAFE + reversible — in the defaultbothmode the def path is untouched and every currently-registered agent registers exactly as today.What changed
parseThreadSpec(threadNote) → AgentSpec(pure):name = metadata.agent;backend/model/mode/definition+ sandbox knobs (workspace/filesystem/network/egress/mounts) from thread metadata, safe defaults when absent (the live agents run on defaults).systemPromptis EMPTY — identity composes from roles①+thread-content②+loadout③ at turn time; the thread body is the rolling summary, never the prompt. Shares the field validators withparseAgentDef(extractedparseBackendField/parseModeField/parseModelField/parseSandboxKnobs— behavior-preserving).DefVaultClient.listThreadNotes()— queries the exact#agent/threadtag,include_contentunset.loadAll, deduped by name — defs first, then threads; a thread whose name a def already registered dedups (def wins inboth). NewreloadThreadmirrorsreloadfor the reactive path; both mode-gated. NewPOST /api/vault/agent-threadwebhook + a thread-watch CREATE trigger (create-only — per-turn upserts would churn the registry; edits converge via the 60s poll).agent_status(metadata.agent_status, defaultenabled) — the enable/disable axis, DISTINCT frommetadata.status(the turn outcome, never read here). Discovery SKIPS adisabledthread, so a retired agent isn't re-registered from its thread.PARACHUTE_AGENT_DISCOVERY=both(default) |thread|def— the cutover is a flag-flip + restart, not a new PR.source: "def"|"thread"on the agent listing + a per-agent boot log line.reloadThread(deleted)); no status stamp / no grant registration for thread-sourced agents (only#agent/rolecarries capability).Safety
The 4am weave has no retry. In
bothmode (default) the def path is completely untouched —loadAlllists defs first and instantiates them exactly as before; threads only dedup against them (or add agents with no def). Verified: full suite 1413 pass / 0 fail,tsc --noEmitclean. No test boots a live daemon (ephemeralBun.serve({port:0})+ injected recorders).Cutover (orchestrator's gated steps, not in this PR)
both(default) — additive, byte-identical for uni/eco-civ.agent_status: disabledon the retired agents' threads (steward, uni-evolve, uni-weaver).PARACHUTE_AGENT_DISCOVERY=thread, restart, confirmsource=thread, watch a real weave fire.🤖 Generated with Claude Code
https://claude.ai/code/session_01T6HAzWsgiJy4ndsWSCWY5S