fix(agents): launch panic + parallel concurrent agent dispatch (v0.1.12)#9
Merged
Merged
Conversation
Root cause #1 (panic on launch): crates/archon-memory/src/embedding/openai.rs::request_batch called reqwest::blocking::Client::send() WITHOUT block_in_place wrap. reqwest::blocking constructs a tokio runtime per call; from inside an async tokio task this panics with "Cannot start a runtime from within a runtime / thread is being used to drive asynchronous tasks". Every agent dispatch that touched memory triggered this. Root cause #2 (no parallel even after panic fix): crates/archon-core/src/subagent.rs::run dispatched pending_tools in a serial for-loop, so N tool_use blocks in one turn ran one-by-one. Reference: claurst (third-party Rust port of Claude Code) at crates/query/src/lib.rs:1815-1944 implements parallel tool dispatch using futures::future::join_all over Vec<Either<ready, execute>> in a three-phase split. join_all preserves input order natively. Mirrored. Fix: - A. Wrap OpenAIEmbedding::embed in tokio::task::block_in_place so reqwest::blocking calls run on a thread tokio knows is allowed to block. No more nested-runtime panic. - B. Refactor subagent.rs::run tool dispatch to claurst's three-phase pattern with futures::future::join_all over Either<Left blocked, Right execute>. Order-preserving, simple, proven. N concurrent tool calls per turn. - C. NO change to AgentTool::execute. Verified reentrant — no global lock serializes concurrent invocations. AGS-104/105/107 contracts preserved unchanged. Added barrier-based regression test asserting two concurrent AgentTool::execute calls run in parallel and BACKGROUND_AGENTS holds 2 simultaneous entries at the rendezvous. Tests added: - archon-memory: regression test confirming embed() inside multi_thread runtime no longer panics (returns 401 from fake key, not a panic) - archon-core::subagent: parallel-tool-dispatch test asserts 3 stub tool calls complete in 0.40s (serial baseline ~0.90s) AND results returned in input order - archon-tools::agent_tool_parallel barrier test asserts deterministic reentrancy via tokio::sync::Barrier rendezvous + BACKGROUND_AGENTS count = 2 mid-flight - bin agent_parallel_smoke E2E: 3 concurrent AgentTool::execute calls in 0.50s (serial baseline ~1.50s) Test results: - cargo nextest run --workspace: ALL PASS, zero failures - cargo fmt --check: PASS - cargo build --release --bin archon -j1: PASS Version: 0.1.11 -> 0.1.12.
ste-bah
added a commit
that referenced
this pull request
May 4, 2026
…re isolation Phase 4 ships routing engine, DAG wave grouping, conditional specialist selection from .archon/specs/gametheory.yaml, and final-stage assembly (scanner/mapper/writer/combiner/style_applier). Tier 1 classification and specialist execution remain stubs in Phase 4: - generate_synthetic_fingerprint uses keyword regex matching - execute_specialist_stub returns templated placeholder text per agent - CLI prints a NOTE banner on every run/replay flagging stub mode Phase 5 wires real LLM agent execution while retaining keyword fallback. Cold-read audit fixes from #8 + #9: - resolve_spec_path search ladder: --spec-path flag, $ARCHON_SPEC_PATH env, upward walk 5 levels, ~/.archon/specs/, /etc/archon/specs/. GameTheoryError::SpecNotFound enumerates all searched paths on miss. - Failure isolation design + test hook (-FORCE-FAIL-FOR-TEST agent_key suffix). failed_specialists Vec<(key, msg)> in FullPipelineResult. Run status "partial" when mixed success/fail, "completed" otherwise. [FAILED] placeholder section in combiner output. - shadow_games_count condition removed from spec (Option B). Agent is mandatory so condition never evaluated. - CLI NOTE banner in run + replay output until real agents wired. 7 new Cozo relations (gt_routing_decisions, gt_enabled_specialists, gt_skipped_specialists, gt_specialist_outputs, gt_sections, gt_final_reports, gt_provenance_edges) all use key=>values syntax. Idempotent via existing run_create + COZO_RELATION_ALREADY_EXISTS const. CLI: archon gametheory {run, list-runs, show, inspect-routing, replay} [--spec-path PATH] [--classify-only]. Tests: gametheory 14 -> 49 (+35 new). Phase 1+2 sealed at 62/62 archon-docs.
6 tasks
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
THE central failure that's dragged on for 2 weeks. Discovery worked, listing worked, permissions worked — agents never actually launched. Now they do, AND N concurrent agents per turn.
Root cause #1 — panic on launch
crates/archon-memory/src/embedding/openai.rs::request_batchcalledreqwest::blocking::Client::send()WITHOUT ablock_in_placeboundary.reqwest::blockingconstructs a tokio runtime per call; from inside an async tokio task this triggers tokio's nested-runtime panic: "Cannot start a runtime from within a runtime / thread is being used to drive asynchronous tasks." Every agent dispatch that touched memory crashed.Root cause #2 — no parallel dispatch
crates/archon-core/src/subagent.rs::runiteratedpending_toolsin a serialforloop. When the LLM emitted N tool_use blocks in one turn, they ran one after another — no concurrency.Fix
OpenAIEmbedding::embedbody intokio::task::block_in_place. Panic gone./tmp/claurst/src-rust/crates/query/src/lib.rs:1815-1944):futures::future::join_alloverVec<Either<Left ready, Right execute>>— concurrent execution, order preserved nativelyAgentTool::execute. Verified reentrant by code inspection: BACKGROUND_AGENTS uses per-agent_idinserts, status/result_slot/cancel_parent are per-call Arcs, no global serialization. AGS-104/105/107 contracts preserved unchanged. Added barrier-based regression test for deterministic concurrency proof.Test plan
embed()inside multi_thread runtime returns 401 from fake key, no panic (0.79s)tokio::sync::Barrier::new(2)rendezvous proves both subagents in flight simultaneously, BACKGROUND_AGENTS count = 2 at rendezvous (<1ms wall-clock)