Skip to content

[AAASM-1184] ✨ (pydantic_ai): Wrap Tool._run execution in spawn_context_scope#41

Merged
Chisanan232 merged 3 commits into
masterfrom
v0.0.1/AAASM-1184/feat/pydantic_ai_tool_spawn
May 9, 2026
Merged

[AAASM-1184] ✨ (pydantic_ai): Wrap Tool._run execution in spawn_context_scope#41
Chisanan232 merged 3 commits into
masterfrom
v0.0.1/AAASM-1184/feat/pydantic_ai_tool_spawn

Conversation

@Chisanan232
Copy link
Copy Markdown
Contributor

@Chisanan232 Chisanan232 commented May 9, 2026

What changed

Each allowed Pydantic AI tool call now executes inside a spawn_context_scope so
any child agent initialised during tool execution inherits full lineage
(spawned_by_tool, delegation_reason, parent_agent_id, depth).

A new LineageRegistry provides children_of / ancestors_of graph queries over
the parent–child relationships built from SpawnContext data.

Pre-existing ruff violations in pydantic_ai/patch.py (UP035/B010/B009/I001) are
fixed in the same commit.

Why

AAASM-1184 — the final subtask of AAASM-212. The three earlier subtasks already
covered Agent.run spawn interception (AAASM-1182), CrewAI team_id / delegation_reason
/ hierarchical kickoff (AAASM-1183), and cross-framework integration tests
(AAASM-1144). This subtask completes the lineage chain at the tool-call boundary so
every sub-agent spawned by a tool is traceable back to its tool invocation, and
operators can query the spawn tree via children_of / ancestors_of.

Changes

agent_assembly/adapters/pydantic_ai/patch.py

  • In patched_run (inside _apply_tool_run_patch), after governance allow,
    wraps original_run call in spawn_context_scope(SpawnContext(...)) with:
    • spawned_by_tool = tool_name
    • delegation_reason = f"tool:{tool_name}"
    • parent_agent_id = agent_id or ""
    • depth = _current_spawn_depth()
  • Fixed pre-existing lint violations: UP035 (Mapping from collections.abc),
    B010 (agent_cls.run = / agent_cls.run_sync = / tool_cls._run =),
    B009 (args.model_dump), I001 (import sort).

agent_assembly/core/lineage.py (new)

  • LineageRegistry — thread-safe in-memory graph: record(agent_id, parent_agent_id),
    children_of(parent_id) → list[str], ancestors_of(agent_id) → list[str].
  • Exported from agent_assembly.core.

agent_assembly/core/__init__.py

  • Lazy-import export of LineageRegistry alongside existing init_assembly / AssemblyContext.

test/unit/adapters/pydantic_ai/test_pydantic_ai_spawn_patch.py

  • New TestApplyToolRunPatch class (9 tests): spawned_by_tool, delegation_reason,
    parent_agent_id from ctx, depth increment, reset on completion and exception,
    denied tool skips spawn ctx, idempotent apply, revert restores original.

test/unit/core/test_lineage_registry.py (new)

  • 13 unit tests covering record, children_of, ancestors_of, __len__,
    overwrite, unknown agents, multi-level chains.

test/integration/test_spawn_lineage_integration.py

  • Test 9: end-to-end pydantic_ai tool spawn context via patched Tool._run,
    verifying all SpawnContext fields and post-call reset.
  • Test 10: full AC [AAASM-48] ✨ (adapters): Bootstrap FrameworkAdapter architecture #5 coverage — patched tool sets _SPAWN_CTX, child agent
    reads parent_agent_id from it and calls registry.record(), then
    children_of and ancestors_of return correct lineage.

Acceptance criteria

AC Status
@agent.tool functions set _SPAWN_CTX before invoking tool body
spawned_by_tool = tool function name
delegation_reason = f"tool:{tool_name}"
Agent.run / Agent.run_sync unchanged (no regression)
Integration test: children_of/ancestors_of return correct lineage
Full test suite green ✅ 327 passed, 9 skipped

How to verify

# Unit tests — tool spawn context
.venv/bin/python -m pytest test/unit/adapters/pydantic_ai/test_pydantic_ai_spawn_patch.py -v
# → 19 passed

# Unit tests — LineageRegistry
.venv/bin/python -m pytest test/unit/core/test_lineage_registry.py -v
# → 13 passed

# Integration tests (Tests 9 + 10)
.venv/bin/python -m pytest test/integration/test_spawn_lineage_integration.py -v
# → 10 passed

# Full suite
.venv/bin/python -m pytest test/ -q
# → 327 passed, 9 skipped

Closes #AAASM-1184

Each allowed tool call now sets a SpawnContext with spawned_by_tool=tool_name
and delegation_reason="tool:<name>" so child agents inherit full lineage.
Also fixes pre-existing UP035/B010/B009/I001 ruff violations in the file.

Closes #AAASM-1184
TestApplyToolRunPatch (9 tests): spawned_by_tool, delegation_reason,
parent_agent_id from ctx, depth increment, reset on completion and exception,
deny skips spawn ctx, idempotent apply, revert restores original.

Integration Test 9: end-to-end pydantic_ai tool spawn context through
patched _run verifying all SpawnContext fields.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 9, 2026

Codecov Report

❌ Patch coverage is 90.00000% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
agent_assembly/core/__init__.py 20.00% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

Thread-safe in-memory graph keyed on agent_id → parent_agent_id.
record(), children_of(), ancestors_of() enable querying the spawn tree
built from SpawnContext lineage data.

Exported from agent_assembly.core. Integration Test 10 proves the full
chain: patched Pydantic AI Tool._run sets _SPAWN_CTX → child agent reads
parent_agent_id → LineageRegistry records the edge → children_of and
ancestors_of return correct lineage. Closes AC #5 of AAASM-1184.
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 9, 2026

@Chisanan232 Chisanan232 merged commit 059d916 into master May 9, 2026
24 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.1/AAASM-1184/feat/pydantic_ai_tool_spawn branch May 9, 2026 04:43
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