Skip to content

Releases: vstorm-co/pydantic-deepagents

0.3.22

Choose a tag to compare

@DEENUU1 DEENUU1 released this 24 May 15:20
a753bd5

[0.3.22] - 2026-05-24

Fixed

  • AttributeError: 'LocalBackend' object has no attribute '_read_bytes' at toolset get_instructions() time (#118, independently authored by @mcauthorn in #119). pydantic-ai-backend 0.2.8 promoted the bytes-read entry point on BackendProtocol from private _read_bytes to public read_bytes and (deliberately) kept no transitional alias. With pydantic-ai-backend>=0.2.7 unbounded, fresh resolutions pulled 0.2.8 transitively, so every toolset that reaches for bytes (context, memory, liteparse, skills/backend) blew up at instructions-load time. Word-boundary rename across all call sites and test mocks.

Changed

  • Bumped pydantic-ai-backend>=0.2.7 → >=0.2.8 (#118, Renovate) — pulls in the exists() predicate, the read_bytes rename (see Fixed above), hashline_edit per-(backend, path) serialization, and the async_execute wire-up in the console toolset's execute tool.
  • Bumped summarization-pydantic-ai>=0.1.4 → >=0.1.5 (#118, Renovate) — batched with the backend bump; pure CI-housekeeping release on the summarization side, no behaviour change.

0.3.21

Choose a tag to compare

@DEENUU1 DEENUU1 released this 24 May 11:45
cb6dc43

[0.3.21] - 2026-05-24

Changed

  • Bumped pydantic-ai-todo floor from >=0.2.1 to >=0.2.2 (#114, auto-opened by the new Renovate config). Brings in pydantic-ai-todo 0.2.2: the new AsyncRedisStorage backend (Redis Hash + companion List, session-scoped, multi-tenant, event-emitter integration) plus a follow-up batch of correctness fixes (remove_todo atomicity via single pipeline, Redis Cluster–safe hash-tagged keys, idempotent initialize()).

0.3.20

Choose a tag to compare

@DEENUU1 DEENUU1 released this 24 May 11:39
499aaf4

[0.3.20] - 2026-05-18

Fixed

  • [WinError 2] crash on Windows when calling the execute tool (#108) — bumped the pydantic-ai-backend floor from >=0.2.4 to >=0.2.7. Releases before 0.2.7 hardcoded ["sh", "-c", command] in LocalBackend.execute(), so every shell invocation on Windows failed with FileNotFoundError: [WinError 2] The system cannot find the file specified, regardless of whether the target executable (e.g. powershell, pwsh.exe) was on PATH. pydantic-ai-backend 0.2.7 routes through _shell_cmd() (cmd /c on win32, sh -c elsewhere) and adds async_execute() with cancellation support.
  • wait_tasks cancellation cascade in subagent orchestration — bumped subagents-pydantic-ai floor to >=0.2.4, which routes both mode="all" and mode="any" through asyncio.wait instead of asyncio.wait_for(asyncio.gather(...)). Previously, when pydantic-ai's _call_tools sibling-cancelled the wait_tasks tool call (or any outer cancel reached the orchestrator), the cascade silently killed every in-flight subagent — surfacing as TaskStatus.CANCELLED with an empty error even though the parent never requested it.

Changed

  • Bumped minimum versions of all pydantic-ai-* sister packages so a fresh install pulls the latest releases by default: pydantic-ai-slim>=1.97.0 (was >=1.77.0), pydantic-ai-backend>=0.2.7 (was >=0.2.4, for both [console] and [docker] extras), summarization-pydantic-ai>=0.1.4 (was >=0.1.3), subagents-pydantic-ai>=0.2.4 (was >=0.2.1), pydantic-ai-shields>=0.3.2 (was >=0.3.1).

Internal

  • # type: ignore[attr-defined] on five BinaryContent attribute accesses in pydantic_deep/processors/eviction.py. pydantic-ai-slim>=1.97 exposes BinaryContent as a PydanticDataclass whose fields and identifier property are invisible to pyright (the attributes exist at runtime — this is upstream type-info incompleteness). Keeps make typecheck green until upstream stubs catch up.

Infrastructure

  • Renovate config (renovate.json) — opt-in dependency bot scoped to the five vstorm-co sibling packages (pydantic-ai-todo, pydantic-ai-backend, summarization-pydantic-ai, subagents-pydantic-ai, pydantic-ai-shields). All other dependencies are explicitly disabled. New releases of these packages will get grouped PRs that bump both pyproject.toml floors and uv.lock, with auto-merge on green CI. Activates once the Renovate GitHub App is installed on the vstorm-co organization.

0.3.19

Choose a tag to compare

@DEENUU1 DEENUU1 released this 14 May 01:13

[0.3.19] - 2026-05-14

Added

  • PeriodicReminderCapability — periodic task reminders for long agent runs (#94) — injects a "what are you supposed to be doing" reminder into the message history every N model-request turns to prevent agent drift on long, tool-heavy runs. Uses before_model_request and per-run state isolation via for_run().

    • Four CLI modes via a new /remind command: off, first (zero-cost — re-states the first user message), context (zero-cost — compact transcript), llm (uses Claude Haiku / GPT mini / Gemini Flash to summarize progress).
    • LLMReminderGenerator with exception fallback to the zero-cost default.
    • Three render styles: system_reminder_tag (default), developer_note, user_prompt.
    • create_deep_agent() gains a periodic_reminder: bool | PeriodicReminderConfig | None = None parameter.
    • CLI: enabled by default in llm mode; configurable via periodic_reminder and reminder_mode keys in config.toml.
    • New top-level exports: PeriodicReminderCapability, PeriodicReminderConfig, ReminderGenerator, LLMReminderGenerator, make_config_for_mode.
  • MessageQueue — mid-run message delivery (steering & follow-up) (#100) — lets external code (CLI keystrokes, webhooks, subagents) push messages into a running agent loop without cancelling and restarting it, preserving in-flight tool results and the prompt cache.

    • Steering messages are injected before the next LLM call via MessageQueueCapability.before_model_request. To avoid issues with downstream capabilities that strip lone trailing ModelRequest nodes, the steering UserPromptPart is merged into the last existing ModelRequest.
    • Follow-up messages are queued for delivery when the agent would otherwise stop, triggering a re-entry via the new run_with_queue() helper.
    • Two delivery modes: one_at_a_time (default) and all (drain entire queue based on the head message's mode).
    • DeepAgentDeps.message_queue field, propagated by reference through clone_for_subagent() so subagents can steer the parent.
    • create_deep_agent() gains a message_queue: MessageQueue | None = None parameter.
    • CLI: >>text mid-run = steering, plain text mid-run = follow-up, !cmd stays as shell command in all states. Side-panel QueuedWidget shows pending counts. Stale steering messages are surfaced as a warning when the run ends before reaching another LLM call, and follow-ups left over from a cancelled run are discarded with a count-only notification.
    • New top-level exports: MessageQueue, MessageQueueCapability, QueuedMessage, run_with_queue, format_steering, format_follow_up.
  • Programmatic skills parameter on create_deep_agent (#97) — accepts list[Skill] instances directly, complementing the existing skill_directories= discovery path. Emits a UserWarning when skills= or skill_directories= are provided alongside include_skills=False.

  • Docker sandbox environment variable support (#99 — fixes #98) — wires up the RuntimeConfig.env_vars plumbing that the programmatic DockerSandbox API already supported but the CLI and full_app example never exposed.

    • sandbox_env_vars: dict[str, str] and sandbox_env_file: str | None fields on CliConfig; matching parameters on create_cli_agent().
    • Three-level priority merge: config.sandbox_env_vars (lowest) → .env file → explicit sandbox_env_vars (highest).
    • examples/full_app/app.py auto-loads examples/full_app/.env into the SessionManager's default RuntimeConfig.
    • Uses RuntimeConfig(cache_image=False) to prevent secrets from being baked into cached Docker image layers.
    • _write_toml() extended to emit [table] sections for dict values, enabling round-trip persistence via set_config_value().

Fixed

  • Esc to interrupt, tool spinner lifecycle, and empty message cleanup (#96 — closes #93):

    • Esc now interrupts a running agent (previously Ctrl+C only); focuses input when idle. Centralized on DeepApp.action_escape_key so any screen-level handler uses the same cancellation path.
    • Fixed a ToolCallWidget.on_mount race where complete() arriving before mount left the spinner timer uninitialized — the widget now renders its final state immediately when not in the pending state.
    • AssistantMessage.complete_tool_call is now idempotent (only acts on widgets still in the pending state), preventing the cancellation drain from overwriting correctly completed results.
    • /load session replay marks orphaned tool calls (from previously interrupted sessions) as "Interrupted" instead of leaving spinners hung; switched to isinstance checks against ToolCallPart / ToolReturnPart / UserPromptPart / TextPart and uses part.args_as_dict() for correct label display.
    • Empty assistant message bubbles are removed when a run is cancelled before producing any output, thinking, or tool calls.
    • The hints bar shows context-aware shortcuts (Esc interrupt) while the agent is running.
  • create_deep_agent() rejected skills= kwarg (#97 — fixes #95) — callers using skills=[Skill(...)] previously got UserError: Unknown keyword arguments: 'skills' because the kwarg fell through to pydantic-ai's Agent() constructor.

0.3.18

Choose a tag to compare

@DEENUU1 DEENUU1 released this 05 May 12:01

[0.3.18] - 2026-05-05

Fixed

  • EvictionCapability dropped BinaryContent (e.g. screenshots) from ToolReturn results — previously, any ToolReturn(return_value=..., content=[..., BinaryContent(...)]) was collapsed into a plain string before the size check, so the multimodal content (images, audio, PDFs) was silently discarded along with a text eviction message. The capability now only measures and evicts return_value; the content list and metadata are always preserved by re-wrapping the result. (#90)

Fixed

  • DeepAgentDeps was missing the checkpoint_store field — the checkpointing middleware already resolved the store via getattr(deps, "checkpoint_store", None) and the docs instructed users to pass it at construction time, but the field was never declared on the dataclass so assignments were silently ignored and type checkers raised attr-defined errors. The field is now properly declared as checkpoint_store: Any = None and propagated as a shared reference through clone_for_subagent(). (#87)

Added

  • Binary content pruning via max_binary_content — a new before_model_request hook in EvictionCapability bounds the number of multimodal binary parts kept in model-visible history. Older BinaryContent values (from both UserPromptPart.content and ToolReturnPart.content) are written to the backend at deterministic paths (/large_tool_results/binary_{id}.{ext}) and replaced with a compact read_file-able text reference so the agent can still retrieve them on demand. If a backend write fails, the binary is left in place to avoid data loss.
    • EvictionCapability gains a max_binary_content: int | None field (default 3).
    • create_deep_agent() gains a matching max_binary_content: int | None = 3 parameter across all overloads; pass None to keep every binary in history.
    • New constants exported from the top-level package: DEFAULT_MAX_BINARY_CONTENT, BINARY_PRUNED_TEMPLATE.
    • Storage paths use BinaryContent.identifier (a stable SHA1 of the bytes), making re-pruning the same binary idempotent.

0.3.17

Choose a tag to compare

@DEENUU1 DEENUU1 released this 22 Apr 14:32
140de9a

[0.3.17] - 2026-04-22

Added

  • LiteparseToolset — document parsing via LiteParse

    • New toolset at pydantic_deep.toolsets.liteparse
    • Tools: parse_document (text extraction) and screenshot_document (per-page images)
    • Reads files from any backend as bytes — works with StateBackend, LocalBackend, DockerSandbox
    • Optional OCR via built-in Tesseract or pluggable HTTP server (PaddleOCR, EasyOCR)
    • Lazy parser initialization — the Node.js CLI is found/installed on first tool call
    • Configurable: ocr_enabled, ocr_language, ocr_server_url, dpi, max_pages
    • Graceful error messages when the liteparse package or Node.js CLI is not installed
    • Enabled via include_liteparse=True in create_deep_agent()
  • liteparse optional extra in pyproject.toml

    • pip install pydantic-deep[liteparse] installs the Python wrapper
    • Node.js >= 18 and npm install -g @llamaindex/liteparse are required separately

0.3.16

Choose a tag to compare

@DEENUU1 DEENUU1 released this 22 Apr 12:25
f4181c8

[0.3.16] - 2026-04-22

Changed

  • instructions now replaces BASE_PROMPT instead of appending to it — previously, passing instructions="..." to create_deep_agent() produced a system prompt of BASE_PROMPT + "\n\n" + instructions. Now instructions is used verbatim as the full system prompt. instructions=None (the default) keeps the existing behaviour — BASE_PROMPT is used automatically. Users who want to extend the default rather than replace it can do so with an f-string: instructions=f"{BASE_PROMPT}\n\nYour extra text". BASE_PROMPT is exported from the top-level package. (#84, reported by @rremilian)
  • Subagent and team-member factories always prepend BASE_PROMPT — agents spawned automatically by the task() tool or spawn_team() continue to receive BASE_PROMPT followed by their task-specific instructions, so subagent behaviour is unchanged.
  • apps/deepresearch double-prompt bug fixedMAIN_INSTRUCTIONS already contained BASE_PROMPT; it was previously duplicated in the final system prompt because the old append logic prepended it again. The new semantics resolve this without any change to the deepresearch app itself.

0.3.15

Choose a tag to compare

@DEENUU1 DEENUU1 released this 17 Apr 14:04
aa7610a

[0.3.15] - 2026-04-17

Fixed

  • PatchToolCallsCapability caused ValidationException: duplicate Ids on Bedrock when tools raised ModelRetry — when a tool raised ModelRetry, pydantic-ai records the retry as a RetryPromptPart (carrying the original tool_call_id) on the following ModelRequest, not as a ToolReturnPart. The patch processor only scanned for ToolReturnPart when deciding whether a ToolCallPart was orphaned, so it injected a synthetic ToolReturnPart with the same id — leaving the request with two parts sharing one tool_call_id. Strict providers (Bedrock minimax.minimax-m2.5 and others) rejected the request with The toolResult blocks at messages.N.content contain duplicate Ids. The processor now treats RetryPromptPart as a valid answer to a ToolCallPart, so no synthetic return is injected and the history remains valid. (#79, reported by @thatGreekGuy96)

0.3.14

Choose a tag to compare

@DEENUU1 DEENUU1 released this 16 Apr 17:14
b1883f2

[0.3.14] - 2026-04-16

Fixed

  • Subagents ignored parent web_search/web_fetch settings — the default subagent factory in create_deep_agent hardcoded web_search=True and web_fetch=True, overriding the parent agent's configuration. On Bedrock and Vertex Anthropic models this produced a 400 error (web_fetch_20250910 not accepted), because the beta web tools are not supported there. The factory now propagates the parent agent's web_search and web_fetch flags to spawned subagents. (#77, reported by @SvdR82)

0.3.13

Choose a tag to compare

@DEENUU1 DEENUU1 released this 13 Apr 14:04

[0.3.13] - 2026-04-13

Fixed

  • User-provided tools lost metadata when passed via tools= parameter — tools registered through create_deep_agent(tools=[...]) were previously added via agent.tool(tool.function) after construction, which hardcoded takes_ctx=True and discarded all Tool-level metadata (name, description, prepare, max_retries, requires_approval, timeout). Tools are now passed directly to the Agent constructor, preserving all metadata and correctly honouring the original takes_ctx value. (PR #75 by @ilayu-blip)