Repository navigation
feat(agents): add the Pydantic AI agent - #338
Conversation
Ship a Pydantic AI agent in the agents bundle, beside Claude Code and the others, at @local/agentenv-framework/agents/pydantic-ai (alias `pydantic-ai`). The agent-env protocol SDK serves the A2A endpoint and its extensions; each turn runs a Pydantic AI Agent in process with the Pydantic AI Harness Coder tools (shell, file tools, sub-agents) in a LocalWorkspace, the task's MCP servers as MCPToolsets and installed skills through the harness's Skills. A context's message history is persisted, so later turns continue it, its messages are the live trajectory, and snapshots carry it with the files attached in it. The model is called through the [model] endpoint as an OpenAI-compatible one; a `vllm:` prefix picks Pydantic AI's vLLM provider. Pydantic AI's own Agent.to_a2a is not used: it serves plain A2A, without the agent-env extensions the validator checks. Also: the fake OpenAI endpoint answers streamed requests with server-sent chunks, which Pydantic AI always asks for.
…hreaded writes before a cancel lets go of the locks A snapshot whose messages.json was JSON but not Pydantic AI messages replaced the conversation and workspace, then failed the next turn; the runtime now validates the messages before anything is replaced. A turn or snapshot cancelled while a thread wrote its files released its locks before the write ended; to_completion waits for the thread before re-raising.
|
🤖 Automated Claude routine — Env Pod PR Context Review. This is a bot, not Edgar Arakelyan; not a human review. Context from a sibling PR and from #345 adds a second agent (
Separately, this branch looks behind bundles = [image.name for image in BUNDLE_IMAGES]
…
assert "agentenv-gateway" in planned["infra"] and bundles == [
"agentenv-claude-code", "agentenv-codex", "agentenv-gemini", "agentenv-opencode", "agentenv-openhands",
"agentenv-pi", "agentenv-proxy", "agentenv-mail-mcp"]So after a rebase the list also needs Each reviewer sees one diff at a time, so none of this shows up on either PR on its own. Offering the comparison, not a verdict on merge order. Generated by Claude Code |
Keeps both sides of the image registrations main added beside this one (the mail-mcp example env and the ubuntu-24.04 base computer) in infra_build.py, dependabot.yml and the infra images test. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
With neither agent-config's model nor PYDANTIC_AI_A2A_MODEL set, every task failed as pydantic_ai.no_model, so an agent other agents message directly, like the A2A validator's peer, never answered. It now falls back to anthropic/claude-sonnet-4-6, as the other bundled agents have a default. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Keeps the Letta Code agent main added beside this one in the shipped aliases and the bundle and infra image tests. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…store, and bound inline attachments Installed in a home directory, the agent works there, so its own ~/.pydantic-ai-a2a is inside the workspace. A workspace restore deleted it, the staged conversation with it, and the restore failed after the workspace had changed, with every other conversation and skill gone. Workspace snapshots now leave that entry out and restores keep it. An inline file part was decoded and written on the event loop with no size check; it now gets the 256 MiB limit downloaded ones have, checked before it is decoded, and is written in a thread. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
| """The name of ``directory``'s entry that ``path`` is in, as the agent's home is in a workspace an install in a | ||
| home directory works in; None when ``path`` is outside ``directory``.""" | ||
| try: | ||
| return path.resolve().relative_to(directory.resolve()).parts[0] |
There was a problem hiding this comment.
_entry_holding selects the first directory under the workspace, not just the agent's state directory. If the shipped image runs with PYDANTIC_AI_A2A_WORKSPACE=/home, the state lives at /home/agent/.pydantic-ai-a2a, but saving skips all of /home/agent, including project files there. Loading also leaves that whole directory unchanged. Both calls can return success without saving or restoring those files.
Exclude and preserve only the agent's state directory, not its whole ancestor.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agent_env/agents/agents/pydantic-ai/pydantic_ai_agent.py
Line: 579
Comment:
**Snapshots skip project files**
`_entry_holding` selects the first directory under the workspace, not just the agent's state directory. If the shipped image runs with `PYDANTIC_AI_A2A_WORKSPACE=/home`, the state lives at `/home/agent/.pydantic-ai-a2a`, but saving skips all of `/home/agent`, including project files there. Loading also leaves that whole directory unchanged. Both calls can return success without saving or restoring those files.
Exclude and preserve only the agent's state directory, not its whole ancestor.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Ship a Pydantic AI agent in the agents bundle, beside Claude Code and the others, at
@local/agentenv-framework/agents/pydantic-ai (alias
pydantic-ai).The agent-env protocol SDK serves the A2A endpoint and its extensions; each turn runs a Pydantic AI
Agent in process with the Pydantic AI Harness Coder tools (shell, file tools, sub-agents) in a
LocalWorkspace, the task's MCP servers as MCPToolsets and installed skills through the harness's
Skills. A context's message history is persisted, so later turns continue it, its messages are the
live trajectory, and snapshots carry it with the files attached in it. The model is called through
the [model] endpoint as an OpenAI-compatible one; a
vllm:prefix picks Pydantic AI's vLLM provider.Pydantic AI's own Agent.to_a2a is not used: it serves plain A2A, without the agent-env extensions
the validator checks.
Also: the fake OpenAI endpoint answers streamed requests with server-sent chunks, which Pydantic AI
always asks for.
Verified: unit tests (
tst/unit/agents/pydantic_ai, 34),tst/integration/cli/run_bundle_pydantic_ai_test.py(6, real Docker against the fake OpenAI endpoint),ruff check, andagent-env a2a-agent validatelocally against an OpenAI-compatible vLLM endpoint: every extension the agent advertises passed (agent-config, mcp-config, trajectory, skill-config, snapshot, peer-agents, install/v1); the snapshot changelog is not implemented, as for OpenHands.Fix the overly broad snapshot exclusion before merging.
Fix with agent prompt
Summary
Adds Pydantic AI as a bundled agent, with coding tools, MCP servers, skills, saved conversations, snapshots, and installation support.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR Task[A2A task] --> Agent[Pydantic AI agent] Agent --> Tools[Coding tools and MCP servers] Agent --> History[Saved conversation] History --> Snapshot[Snapshot] Workspace[Workspace files] --> SnapshotReviews (6) · Last reviewed commit: "fix(agents): keep the Pydantic AI agent'..." · Reviewed by Greptile