Archytas 2.0 rebuilds the agent's foundations around multimodal tools, parallel tool execution, and real prompt caching, alongside a modernized build system. Most 1.6.x code continues to work through deprecation shims, but this is a major release — please review the Breaking Changes section before upgrading.
Highlights
True multimodal tools. Tools can now return images, audio, video, and binary content via the new MultiModalResponse type (from_file, from_bytes, from_files). The implementation moves to LangChain's standard content-block model, replacing the previous text-and-image-URL special case and the per-provider workarounds it required.
Parallel tool execution. When the model requests several tools in one step, Archytas now runs them concurrently with asyncio.gather rather than sequentially. The default ReAct prompt encourages batching independent calls.
New lifecycle hooks. The thought_handler callback is replaced by on_react_step(thought, thought_id, tool_calls), fired once per step before dispatch, and on_tool_call_update(tool_call_id, state, **fields), fired on each tool's transitions (running, done, error, cancelled) with timing and output details.
State tools. The new @statetool decorator registers a tool that is both callable by the model and automatically injected by the framework when a condition you define is met. Its output is injected fresh each turn as an ephemeral exchange that is never persisted to history — a clean way to keep the model aware of changing environment state without bloating the conversation or invalidating the cache.
Prompt caching. Archytas now sets cache_control breakpoints for Claude models on Anthropic and Bedrock, reducing latency and cost on multi-turn sessions. Set ARCHYTAS_DISABLE_PROMPT_CACHE=1 to disable. To support this, dynamic context (auto-context and state tools) is now injected as an ephemeral, XML-tagged block at the tail of the message list rather than near the top, keeping the cacheable prefix stable.
Composable prompts. System prompts are assembled from ordered PromptSection pieces via get_prompt_sections(), replacing the monolithic build_prompt(). The framework_prompt class attribute replaces custom_prelude.
Correctness fix for future annotations. Dependency injection (AgentRef, LoopControllerRef, etc.) now resolves correctly under from __future__ import annotations; previously these were silently ignored when annotations were stringified.
Build and packaging. Migrated from Poetry to Hatch with bump-my-version integration, added Docker packaging via docker buildx bake, and updated the quickstart to use uv. Python 3.10+ remains the floor, with no new runtime dependencies.
Breaking Changes
| 1.6.x | 2.0 | Notes |
|---|---|---|
build_prompt(custom_prelude=...) |
get_prompt_sections() / assemble_prompt() |
Function removed. |
prompt= |
custom_prompt= |
Old name retained as an alias. |
custom_prelude= |
framework_prompt= |
Deprecated; warns and maps through. |
thought_handler |
on_react_step + on_tool_call_update |
Removed outright; no shim. |
AutoContextMessage |
InstructionSource |
Still importable; constructing it warns. |
format_tool_result_for_display() |
Centralized content-block path | Removed. |
Additional notes:
ChatHistory.auto_context_messagenow returns a compatibility shim, not anAutoContextMessage;isinstancechecks against it returnFalse.LoopControllerstop-states (STOP_SUCCESS/STOP_FATAL) are currently inert under concurrent tool execution.auto_context_message_token_estimatenow always returns0; useinstruction_token_estimate.auto_update_contextis effectively a no-op.