Releases: vstorm-co/pydantic-deepagents
Release list
0.3.43
Changed
- Requires
subagents-pydantic-ai>=0.2.18(#199) — the subagent toolset no longer defaultsdefault_modelto a library-chosen model; deep-agent construction already passes a model and is unaffected. - Requires
pydantic-ai-backend>=0.2.25(#192) — maintenance bump for theconsoleanddockerextras.
Full changelog: https://github.com/vstorm-co/pydantic-deepagents/blob/main/CHANGELOG.md
0.3.42
Changed
- Requires
pydantic-ai-backend>=0.2.18, which is a bug-fix release worth
taking: a directory listing reported shell-quoted paths, so a directory with a
space in its name was unreachable — the model was handed a path it could not
read back; a glob aborted its whole walk on one unreadable entry and returned a
silently short listing; and a Kubernetes exec reported an unknown status as
success, so every truncated command looked like it had passed.
Added
-
AsyncBaseSandboxandis_async_backendre-exported from
pydantic_deep, alongsideBaseSandbox. SubclassAsyncBaseSandboxfor a
sandbox reached over an async transport — asyncssh, an async HTTP SDK — and
implementexecuteandeditas coroutines; every other file operation is
derived from shell commands, as with the synchronous base.Prefer it to wrapping async code in a synchronous facade.
ensure_asynccannot
see through a facade, so it thread-wraps it and each call then occupies a worker
thread that has to hop back onto the event loop; a sandbox whose own recovery
path also needs a thread deadlocks against its own pool.is_async_backendis
the checkensure_asyncperforms, exposed so a host can ask the same question.
0.3.41
Changed
- A subagent blocked in
ask_parentnow waits 60s, not 300s.
subagents-pydantic-aidefaults to a five-minute wait, which a team member
inherits: one that asks a question while the lead is not polling holds its slot
for the whole timeout, and five minutes of that is indistinguishable from a hung
agent. After the timeout the subagent is told to proceed on its own judgment
rather than being cancelled, so the work still finishes.
Added
create_deep_agent(subagent_ask_timeout_seconds=...)and
DEFAULT_SUBAGENT_ASK_TIMEOUT_SECONDS(60.0), for raising the wait back up when
a human is reliably in the loop.
0.3.40
Agent teams were wired to the subagent execution engine but never actually ran a
member. Four defects compounded, each of them silent: the tools reported success
and the team produced nothing.
Requires subagents-pydantic-ai >= 0.2.12, which adds the programmatic
answer_task / steer_task surface and exposes SubAgentToolset.registry.
Fixed
- Teams registered members in a registry the subagent engine never reads. With
subagent_registry=None— thecreate_deep_agentdefault — the team block built
a freshDynamicAgentRegistry(), sospawn_teamput its members somewhere the
subagenttasktool does not look and everyassign_taskcame back
Error: Unknown subagent. Teams plus subagents was broken in the default
configuration. Teams now sharesubagent_toolset.registry. - A refused delegation was recorded as a started task. The subagent
tasktool
reports an unknown subagent or a busy chat trace as an error string rather than
raising, soassign_task'sexceptnever fired: it set the member torunning
and appended the error to an "Agent running in background" message. The member
then sat atrunningforever. A started task is now identified by itsTask ID:
line, and a refusal marks the memberfailedwith the reason. message_teammatedelivered nothing. It wrote toTeamMessageBus, which no
running member reads — a member is a background subagent and only sees what the
subagent engine hands it, andTeamMessageBus.receive()is called from tests
only. It now routes through the engine:answer_taskwhen the member is blocked
inask_parent,steer_taskwhile it runs, and it says plainly when there is
nothing to deliver into instead of reporting "Message sent".- A finished member left its shared task
in_progressforever, so the lead read
completed work as outstanding.AgentTeam.sync_membercompletes the todo when a
member completes, and releases the claim when one fails so the lead can reassign
it rather than watching a dead member hold it.
Added
create_team_toolset(subagent_toolset=...)— the subagent toolset backing
execution, which is what makesmessage_teammateable to deliver. The existing
registry/task_fn/task_managerarguments still work.TeamMemberHandle.todo_id, linking a member to the shared-todo item it
claimed so finishing the task can close the todo.TestTeamSubagentWiringintests/test_teams.py, which fails on each of the
four defects independently.
Changed
TestCreateTeamToolset::test_message_teammateasserted the"Message sent"that
the third defect shows was a lie; it now asserts the honest outcome.
0.3.38
[0.3.38] - 2026-07-24
MCP resources and skills reach the model, the CLI talks to any
OpenAI-compatible local endpoint, and the todo list stops invalidating the
provider's prompt cache on every mutation.
Added
- MCP resources and
skill://skills are now visible to the model (#180, closes #178) (pydantic_deep/mcp/resources.py,pydantic_deep/mcp/registry.py,pydantic_deep/mcp/config.py,pydantic_deep/mcp/loader.py). pydantic-ai surfaces only an MCP server's tools, so a server publishing skills through FastMCP'sSkillsDirectoryProviderwas unreachable from a delegated agent unless the app hand-rolled a bridge. Setinclude_resources/include_skillson anMCPServerConfig(or in themcpServersJSON) andMCPRegistry.build_active()attaches a second toolset withlist_mcp_resources/read_mcp_resourceand, for skills,list_mcp_skills/load_mcp_skill. It binds to the sameMCPToolset, so tools and resources share one connection and one resource cache. Both flags default to off.- The resource tools are prefixed per server (the config's
tool_prefix, else its name), so several servers can expose their resources in the same run — without a prefix their identical tool names collide and pydantic-ai fails the run. - With
include_skills, the server's skills are listed in the system prompt, so the model knows the guidance exists before it starts calling the server's operational tools. - An unreachable server returns the failure as tool text rather than raising out of
agent.run(), matching howmake_resilientdegrades the tools toolset. - New export:
create_mcp_resources_toolset(alsoMCPResourceProvider,SKILL_URI_SCHEME,SKILL_DOC_NAMEfrompydantic_deep.mcp).
- The resource tools are prefixed per server (the config's
- OpenAI-compatible local endpoints in the CLI (#176, closes #175) (
apps/cli/config.py,apps/cli/providers.py,apps/cli/agent.py,apps/cli/screens/onboarding.py,apps/cli/commands.py,docs/cli/settings.md). Only Ollama worked from the CLI, because it has a provider prefix pydantic-ai recognises; llama.cpp, LM Studio, vLLM and text-generation-webui need anOpenAIChatModelbuilt with a custombase_url, which a plain model string can't carry.CliConfiggainsbase_urlandlocal_api_key, anopenai-compatibleprovider entry is added to the picker, and theopenai-compatible:<name>sentinel is resolved into a real model pointed at that endpoint./providerroutes the choice to a newLocalEndpointModal(base URL + model name + optional key), and keyless local providers report as ready in onboarding. Contributed by @OchnikBartek, requested by @nenoro.
Fixed
-
The
openai-compatible:sentinel is now resolved everywhere, not just increate_cli_agent(#176) (apps/cli/model_resolve.py,apps/cli/agent.py,apps/cli/reminder.py,apps/cli/goal.py,apps/cli/commands.py,apps/cli/credentials.py,apps/cli/screens/onboarding.py). The sentinel is a CLI-only marker that pydantic-ai'sinfer_modelrejects withValueError: Unknown provider: openai-compatible, and only the primary model was being converted — sofallback_model,/remind llm(which degraded to the zero-cost generator with a log warning),/goal(which answered "Evaluator error; continuing." every turn and never completed) and/improveall received the raw string. The conversion moves intoresolve_cli_model, which every site now goes through; plain strings and already-builtModelinstances pass through untouched, and the/improvechain takesstr | Model.OPENAI_COMPATIBLE_API_KEYis registered incredentials.py./providerwrote it, butkeys list,keys setand/keysall iterateCREDENTIALS, so it was invisible and unfixable from the UI. It deliberately has noprovider_id, so it stays out of the key-first first-run flow where picking it would set a model with no endpoint.LocalEndpointModalrejects a scheme-less base URL.localhost:8080/v1built a provider fine and only failed on the first message, with an httpx protocol error that reads like an agent bug.- Known gap:
/forkbranch models and the merge judge model can still be set to the sentinel from the model picker.MergeStrategy.judge_modelandBranchSpec.modelare strings by design (vote-model detection, cache keys), so that fix belongs in its own change.
-
Todo mutations no longer rewrite the system prompt (#182) (
pydantic_deep/instructions.py,pydantic_deep/agent.py,pydantic_deep/spec.py,pydantic_deep/deps.py).create_deep_agentdoesn't useTodoCapability— it builds its own instruction providers — so the static-by-default prompt introduced inpydantic-ai-todo0.2.7 never applied here:make_todo_sectioncalledget_todo_system_prompt(proxy), which appends## Current Todoswhenever the run has any. The instructions open the provider's prompt-cache prefix, so everywrite_todos/update_todo_statusinvalidated the whole cached prefix mid-run. The todo section is now the staticTODO_SYSTEM_PROMPT, with the live list behind a newinclude_current_todos=True(also aDeepAgentSpecfield), matching the upstream flag name. Reported by @jb2197.- The instruction providers no longer touch the todo proxy at all, so
build_instruction_providersdrops itstodo_proxyargument._TodoProxyBinderre-binds the proxy in each tool's owncontextvarscontext (issue #148), which was always the only binding the tools saw. The end-to-endwrite_todospersistence test covers this. - The opt-in list is appended as its own section, so it composes with
tool_search=Trueinstead of being dropped by the lean todo section. DeepAgentDeps.get_todo_prompt()— until now unused by the library — is what renders that section, and now includes each todo's id (- [ ] [id] content, matching upstream) so the model can address a task withupdate_todo_statuswithout re-reading the list.- The 0.3.37 note below claimed pydantic-deep's prompt behavior was unaffected by the upstream default. It wasn't; this is that fix.
- The instruction providers no longer touch the todo proxy at all, so
Changed
- vstorm-co dependency floors raised (#184) (
pyproject.toml):summarization-pydantic-ai>=0.1.11— compression no longer produces a history that providers reject. Withkeep=("messages", 0)(theContextManagerCapabilitydefault) the rebuilt history was a singleModelRequestof system parts only, which Anthropic and Google route into the top-levelsystemparameter — mapping to zero provider messages, so any run long enough to cross the compression threshold failed deterministically. A zerokeepalso no longer summarizes away the in-flight request, and summaries stop accumulating in the system channel. Note for anything reading a summary back out of a compressed history: it's carried by aUserPromptPartnow, not aSystemPromptPart.subagents-pydantic-ai>=0.2.10—wait_tasksused to hard-slice a completed task's result to 2000 characters with no marker, so the orchestrator read a well-formed answer that stopped mid-sentence, assumed the subagent was cut off, and re-delegated work that was already done. Truncated results now say so and name thecheck_task(...)call that returns the full text, and the budget is configurable viamax_result_chars.
ruffcapped below 0.16 in the lint group (pyproject.toml).uv.lockis gitignored, so CI resolved the latest release on every run; ruff 0.16.0 started formatting code blocks inside Markdown, which flags 49 docs andexamples/skills/*/SKILL.mdfiles that have never been formatted — turningruff format --checkred on unrelated PRs. Lifting the cap belongs in a dedicated commit that reformats those files in one go.
0.3.37
[0.3.37] - 2026-07-22
A CLI paste fix and raised floors on the vstorm-co packages, bringing backend
permission-rule hardening, stateful subagent conversations, and a
cache-friendly todo system prompt upstream.
Fixed
- Single-line paste no longer inserts the text twice in the CLI prompt (#179) (
apps/cli/widgets/input_area.py). Textual dispatches aPasteevent to both the subclass and the base-class handler, andPromptInput._on_pasteadditionally calledInput._on_pastedirectly — so a plain single-line paste landed once from the direct call and once again whenMessagePumpreached the base handler. The multi-line path (routing to multiline mode) is unchanged; a single-line paste now falls through to normal dispatch and is inserted exactly once. Ships with a regression test. Contributed by @Sanjays2402.
Changed
- vstorm-co dependency floors raised (#174) (
pyproject.toml):pydantic-ai-backend[console]>=0.2.16(also thesandboxextra) — permission rules are now enforced on every content-returning path ofLocalBackend:read_bytes(closes the image/document leak throughread_file),grep_raw,ls_info/glob_info, and a best-effort path guard onexecute, so adenyrule like**/restricted/**can no longer be bypassed.subagents-pydantic-ai>=0.2.9— stateful subagent conversations viachat_trace_id(a task result's trace ID can be passed back to resume the same subagent with full history) and rich per-task observability onTaskHandle(usage, cost, message history, trace/span IDs), withcheck_task/wait_tasksno longer embedding usage details in tool-return text.
pydantic-ai-todo>=0.2.7(pyproject.toml) — upstreamTodoCapabilityno longer injects the live todo list into the system prompt by default, which was invalidating the provider's prompt-cache prefix on every todo mutation (opt back in withinclude_current_todos=True). pydantic-deep builds its todo instructions through the unchangedget_todo_system_prompt()helper, so its own prompt behavior is unaffected by the new default.
0.3.36
[0.3.36] - 2026-07-18
A configurable MCP handshake timeout for slow-starting servers, and LiteParse
pinned to the 1.x line.
Added
init_timeoutonMCPServerConfigfor slow-starting MCP servers (#167, #171) (pydantic_deep/mcp/config.py,pydantic_deep/mcp/registry.py). pydantic-ai caps the initial connect +initializehandshake at 5s, so a server that does real work on startup (e.g. opens a database connection, ~8s) failed with"Failed to initialize server session"— and re-wrapping with a longer timeout isn't possible, sinceMCPToolsetrejectsinit_timeoutalongside a pre-built client. The new optional field (validated positive;Nonekeeps the 5s default) is forwarded bybuild_mcp_serverto everyMCPToolsetconstruction (stdio, OAuth, http/sse), only when set, and round-trips throughto_dict/from_dictso the CLI persists it inmcp.json. The/mcpTest action's probe window now scales with it —max(10s, init_timeout + 5s), OAuth keeps 180s — so a slow server that connects fine at runtime no longer fails its connection test (apps/cli/modals/mcp_view.py).
Fixed
- LiteParse pinned to the 1.x line (#172, #173) (
pyproject.toml,pydantic_deep/features/liteparse/toolset.py,docs/advanced/liteparse.md). Theliteparseextra's lower bound moves to>=1.1.0— the first release of the Python binding that ships the async API (parse_async/screenshot_async) the toolset uses — and gains a<2.0.0cap, since 2.x dropped that API. The npm CLI install command in the toolset docstrings, the runtime "not installed" message, and the docs is pinned to match (npm install -g @llamaindex/liteparse@^1.2.0), so auto-install and copy-pasted setup can't pull an incompatible 2.x CLI.
0.3.35
[0.3.35] - 2026-07-03
Onboarding and per-user configuration, a dynamic model catalogue in the picker,
credential management from the CLI/TUI, reasoning-effort and project-init
commands, a prompt/reminder overhaul, and a Terminal-Bench harness.
Added
CLI / TUI
- First-run onboarding — on first launch (when no model is configured
anywhere) the CLI walks you through picking a provider, entering its key, and
choosing a model. The choice is saved to the user-level config so it carries
across every project. Re-runnable any time withpydantic-deep onboard. - Credential management —
pydantic-deep keys list / set / removeand an
in-TUI/keyspicker set any of the known credentials (model providers,
Vertex, Logfire, AWS, Azure) from one registry into a git-ignored keystore.
Keys are user-global by default (~/.pydantic-deep/keys.toml) and loaded into
the environment on startup;--projectscopes them to one repo. Real env vars
always win. - Dynamic model catalogue — the
/modelpicker (aliased/models)
now lists recently-used models, the live OpenRouter catalogue (fetched and
cached under~/.pydantic-deep/cache/, refreshed in the background), and every
native provider pydantic-ai recognises (read from itsKnownModelName, keyed
providers first), all with real fuzzy search. On the CLI:pydantic-deep models recent / openrouter / select. Recently-used models are remembered per user. /thinking— change reasoning effort (off → xhigh) from a picker or
/thinking <level>; it applies live and persists./init— analyse the project and write anAGENTS.mdso the agent has
context (and seedMEMORY.md).- Welcome hero — the splash now renders a magenta
pydanticASCII wordmark
and a rotating tip (it was previously a defined-but-never-mounted widget). - Interactive CLI pickers —
keys setandmodels selectopen
arrow-selectable lists with hidden value entry (prompt_toolkit) when run
without arguments; the argument forms stay scriptable.
Framework
- Submodels inherit the primary model when not explicitly configured — an
undefined summarization / reminder / judge model now falls back to the main
model instead of a hard-coded default.
Benchmark
apps/harbor— a HarborBaseInstalledAgentadapter to evaluate the CLI
agent on Terminal-Bench 2.0, with Logfire tracing and per-task trace tags,
installing pydantic-deep into the task container and forwarding the full agent
feature set. A benchmarkAGENTS.mdencodes the task-solving rules.
Changed
- User-level vs project configuration —
load_config()now merges a global
~/.pydantic-deep/config.toml(user defaults: model, theme, thinking) as the
base with the project.pydantic-deep/config.tomlas overrides; environment
variables win over both. The model chosen during onboarding lives in the global
config so new projects don't re-prompt. - Onboarding is triggered by "no model configured" (env / project / global
config) rather than by the absence of~/.pydantic-deep/, which incidental
caches (update check, keystore) created too early to be a reliable signal. - Context files are no longer auto-created.
AGENTS.md,SOUL.mdand
MEMORY.mdare written only by the agent when it decides to (write_memory/
write_file), by/init, or by the user — never scaffolded on launch. Missing
files are silently skipped andwrite_memorycreatesMEMORY.mdon demand, so
the agent works with or without them. - System prompt consolidated into
pydantic_deep/prompts/— one set of
composable fragments + a builder, replacing the scattered CLI/prompt strings;
the oldapps/cli/prompts.pyis now a thin re-export. - Periodic reminder cadence relaxed to every 15 turns (first after 15, no
per-run cap) so long tasks aren't nagged as often. - Ctrl+C aligns with Claude Code / Codex (#154) — it now copies the current
text selection to the clipboard when there is one, and an idle Ctrl+C arms exit
(a second press within 2 s quits) instead of closing on the first press. A
running agent is still interrupted by a single Ctrl+C. Text selection (dragging
to highlight agent output) works via Textual's built-in selection.
Fixed
/modelwas effectively unusable — the picker didn't focus its input (you
couldn't type), the "filter" never actually filtered the list, and pressing
Enter on a typed term submitted the raw text (qwen→ "Unknown model:
qwen") instead of selecting the highlighted match. All three fixed; a
duplicate-id crash when a model appeared in both "recent" and a provider list
was resolved.- Changing the model now updates the input footer live — the session line
under the prompt readmodel_namelazily and only refreshed after an app
restart. - Headless runs survive flaky provider responses — the graceful-exit path
now also catches transport/gateway failures (ModelHTTPError,
httpx.HTTPError, andjson.JSONDecodeErrorfrom a non-JSON gateway body) and
exits 0 so downstream verification can still grade the filesystem, instead of a
hard non-zero crash. - MCP subagents failed in the TUI with
[Errno 9] Bad file descriptor
(#167).run_tui()built the agent beforeapp.run(), so a subagent
agent_factorythat spins up anMCPToolset(StdioTransport(...))bound
fastmcp's async primitives to the orphaned pre-app.run()event loop; when a
task()delegation later used them inside Textual's loop, the stdio connection
died instantly. Agent construction is now deferred toDeepApp.on_mount
(agent_factorybuilt via_build_deferred_agent, before the chat screen
mounts) so those transports bind to the running Textual loop. The "launch the
TUI anyway on failure so the key can be fixed via/provider" behaviour is
preserved.
0.3.34
[0.3.34] - 2026-06-27
A large release: a full CLI/TUI overhaul, a vertical-slice re-organization of the
framework into features/, a new Monitor capability, broad edge-case
hardening, and a documentation rewrite.
Added
Framework
- Monitor — watch & react (
pydantic_deep/features/monitoring/). The agent starts a long-lived command (log tail, CI poll, file watch, dev server) withstart_monitor/list_monitors/stop_monitor; each new line of matching output is pushed back into the conversation via the message queue, so the agent reacts without polling.MonitorManagerdrains the process on an interval, filters lines by an optional regex, and emitsMonitorEventbatches through anon_eventsink. Enabled by default (include_monitoring=True); needs a background-capable backend. - Background process tools surfaced from
pydantic-ai-backend0.2.15 (run_in_background/read_output/kill_shell/list_shells), so dev servers and watchers outlive a singleexecute()call (which kills its whole process tree on timeout). ToolSearchcapability (pydantic_deep/features/tool_search/) — defer situational toolsets so the model discovers them on demand. Off by default in the library, on in the CLI.- A built-in
general-purposesubagent so the agent can delegate arbitrary multi-step work.
CLI / TUI
- New slash commands:
/retry(re-run the last prompt, dropping the previous turn),/export [path](save the conversation to Markdown),/shells(list background processes). - Ctrl+P input-history picker with fuzzy search; fuzzy subsequence matching in the
/command and@file pickers (newapps/cli/fuzzy.py). - Background-shells panel pinned in the activity dock.
- Multi-line paste switches the input to multiline, preserving code blocks.
- Visible attachment chips + drag-and-drop files onto the input; clipboard image paste; quoted
@"path with spaces"so spaced screenshots attach as images. - Interactive
/settingsmodal (changes apply immediately) and an/infomodal;/helpand the command picker now list every command, guarded by a coverage test. - Warm amber (Tau-inspired) default theme with theme-aware chrome (header, status line, input, tool calls, diffs), animated welcome, and a boxed prompt.
Changed
@filereferences now pass the path (backticked) to the agent instead of inlining the whole file — the agent decides how to read it (full, sliced, or grep). Images still attach as multimodal content.!shelland/diffrun off the event loop (no UI freeze on long commands or large repos); the/loadsession picker loads asynchronously, sorts by modification time, and fuzzy-filters.- Lean behavioral prompt sections when
tool_searchis on (tools carry their own descriptions); folders-first directory tree in the context prompt. - Prompt caching enabled on the OpenRouter path (previously only the Anthropic cache keys were set), cutting cost on multi-turn / subagent runs.
- Left sidebar replaced by activity panels pinned above the input; session + workspace moved to a footer; the status line carries live metrics.
- Broad type hardening and de-duplication across the framework (pydantic models for improve insights,
Literalstatus/action enums, typed deps/callbacks/coordinators, tightened public exports, drift guards onDeepAgentSpecand overloads); default models sourced frompydantic_deep.models. - Pinned
pydantic-ai-backend>=0.2.15(background processes, read output ceiling, glob mtime sort, edit staleness guard, image downscaling, Python grep build-dir skip,AsyncCompositeBackend) andsubagents-pydantic-ai>=0.2.8(dropping the localRunUsageshim); addedpillowto thecliextra for image downscaling. - Documentation rewritten in the FastAPI tutorial style and restructured around FastAPI's Learn → Advanced → Reference model. New step-by-step Tutorial — User Guide (
docs/learn/, 13 pages), a rewritten Advanced User Guide (docs/advanced/, 19 pages including new goal-loop and monitor pages), a full CLI guide (docs/cli/, 6 pages), an Applications section covering the reference apps (docs/apps/: DeepResearch, ACP/Zed, Harbor), and new API-reference pages (monitoring, goal, tool-search, message-queue). Concept/example/landing pages carry the same voice; the real Pydantic logo is used in the navbar/favicon; pages superseded by the tutorial were retired and cross-links updated.mkdocs build --strictpasses clean.CLAUDE.mdreflects thefeatures/layout. - Reorganized features into vertical-slice packages under
pydantic_deep/features/. Each feature now lives in one folder (capability.py+toolset.py+service.py/types.py) instead of being smeared acrosstoolsets/andcapabilities/. Top-level imports (from pydantic_deep import …) are unchanged. The old deep import paths remain as deprecation shims (emittingDeprecationWarning) and will be removed in the next minor release.memory:pydantic_deep.toolsets.memory/pydantic_deep.capabilities.memory→pydantic_deep.features.memory.context:pydantic_deep.toolsets.context/pydantic_deep.capabilities.context→pydantic_deep.features.context.browser:pydantic_deep.toolsets.browser/pydantic_deep.capabilities.browser→pydantic_deep.features.browser.eviction:pydantic_deep.processors.eviction→pydantic_deep.features.eviction.patch:pydantic_deep.processors.patch→pydantic_deep.features.patch.history_archive:pydantic_deep.processors.history_archive→pydantic_deep.features.history_archive.stuck_loop:pydantic_deep.capabilities.stuck_loop→pydantic_deep.features.stuck_loop.periodic_reminder:pydantic_deep.capabilities.periodic_reminder→pydantic_deep.features.periodic_reminder.hooks:pydantic_deep.capabilities.hooks→pydantic_deep.features.hooks.message_queue:pydantic_deep.capabilities.message_queue→pydantic_deep.features.message_queue.teams:pydantic_deep.toolsets.teams→pydantic_deep.features.teams.plan:pydantic_deep.toolsets.plan→pydantic_deep.features.plan.checkpointing:pydantic_deep.toolsets.checkpointing→pydantic_deep.features.checkpointing.improve:pydantic_deep.improve/pydantic_deep.toolsets.improve→pydantic_deep.features.improve.skills:pydantic_deep.toolsets.skills/pydantic_deep.capabilities.skills→pydantic_deep.features.skills.forking:pydantic_deep.toolsets.forking/pydantic_deep.capabilities.forking→pydantic_deep.features.forking.liteparse:pydantic_deep.toolsets.liteparse→pydantic_deep.features.liteparse.
Fixed
- Subagents crashing with
'RunUsage' object is not callableunder pydantic-ai 2.0 (usage became a property), fixed upstream insubagents-pydantic-ai0.2.8 and re-pinned here. - Context-usage warning spammed on every update — it now warns once per crossing above 90% with hysteresis (re-arms below 85%), instead of on every
ContextUpdated. /undoleft the removed turn on screen — it now removes the turn's widgets too (MessageList.remove_last_turn), keeping the transcript in sync with history./retryreuses the same path.- Status bar overflow that ghosted text beside the input.
- Numerous edge cases: forking auto/vote merge and abort deadlocks; skills frontmatter / path containment / reserved words; eviction preview-on-write-failure and collision-safe ids; patch tool-call rebuild preserving
ModelRequestfields; MCP stdio/stderr screen leaks; dropped uploads; corrupt-archive recovery; and Python warnings leaking onto the TUI. - CI: docs build (stale
eviction.create_content_previewreference) andmypyerrors.
0.3.33
[0.3.33] - 2026-06-26
Fixed
- Agent memory injection now keeps the most recent lines, not the oldest (#157) (
pydantic_deep/toolsets/memory.py).format_memory_prompttruncated an over-budgetMEMORY.mdby keeping the firstmax_lines, butwrite_memoryappends new content to the end of the file, so the newest observations were the first to drop out. Truncation now keeps the recency tail (the dropped-line marker moves above the kept tail). Two additions from the same report: authors can pin a foundational head with a<!-- deep:pin-end -->marker (DEFAULT_PIN_END_MARKER), which is always injected in full so it survives truncation; and injection can be budgeted in approximate tokens via a newmax_tokensthat takes precedence overmax_lines(reusing theNUM_CHARS_PER_TOKENheuristic).AgentMemoryToolsetandMemoryCapabilitygainmax_tokens/pin_marker; subagents acceptextra.memory_max_tokens/extra.memory_pin_marker. - Subagent delegation no longer fails with a
read_memorytool name collision (#155) (pydantic_deep/agent.py). Withinclude_memory=Trueandinclude_subagents=True(both default), the default subagent factory passedinclude_memory=Trueinto each subagent's owncreate_deep_agent, which registered a secondAgentMemoryToolset('deep-memory', under the wrong "main" namespace) on top of the one_inject_subagent_memory_toolsetalready injects — a regression since 0.3.30 that made every delegation fail withAgentMemoryToolset 'deep-memory' defines a tool whose name conflicts ...: 'read_memory'. The factory no longer creates its own memory toolset; the injected one, correctly namespaced to the subagent, is the single source.