v0.21.0
✨ New Features
🖥️ A2A Embedded Chat UI
- Added a browser-based chat UI served directly by the A2A server (root
/,
reserved/_a2a-ui/prefix) so you can chat with your agents without a
separate client. - Streaming responses with append/replace artifact semantics, thinking blocks,
status pills, and live task recovery after a page refresh (GetTask →
resubscribe). - Conversation management: create/rename/delete, persisted in IndexedDB;
full A2AcontextId/taskIdcontinuity. - Agent selector per turn,
input-requiredcontinuation locking, inline file
upload (up to 5 files, 10 MB each) as A2A raw parts, and retry support. - Optional API-key auth: the key is kept in
sessionStorageonly (never
persisted); public UI routes stay public while protected routes require a
Bearer token. The public/_a2a-ui/configendpoint never leaks the key. - New public
/agentsroute for client-side agent listing.
🧠 Reasoning Effort Control (--reason-effort)
- New CLI argument
--reason-effort(none,minimal,low,medium,
high,xhigh) on all commands (chat / console / GUI, A2A server, ACP
agent, job). - New per-agent
reason_effortfield in agent configs (agents.toml),
editable from the GUI agent editor. /thinkslash command now accepts reasoning levels; the legacy numeric
thinking budget still works.- Documented reasoning precedence: user switch (
/think) > CLI > agent configmodel default. New
reasoning_selectionmodule shares canonical levels and
an Anthropic-family token-budget adapter with the ACP model controller.
📇 Reworked Model Selection
- Typed value objects (
RuntimeModelInput,ModelSelection,
ModelSelectionSource) with a single documented precedence chain:
user switch (/model) > explicit runtime args > agent config > detected
AGENTCREW_MODEL_ID> persisted last-used > provider default. /modelforce switches now survive config reloads;is_forced/is_pinned
are explicit per-selection properties.- Detected values are never masked as explicit arguments, so precedence stays
honest across all startup routes (console, GUI, A2A server, ACP, job). - Every local agent now owns a dedicated, uncached LLM service so per-agent
reasoning mutations never leak to another agent.
🔍 Full-text Conversation Search (PR #48 by @fy17ohhh)
- Console conversation browser now searches both titles and message
content with highlighted match previews (role context + ellipses). - Session-local lazy index: histories are normalized once (Unicode casefold,
whitespace collapse) and cached, so later queries skip filesystem reads. - Internal-only content (memory preamble, injected file blocks, non-chat tool
blocks) is excluded from the index.
🤖 New Models
- Qwen 3.8 2.4T A95B (DeepInfra, Fireworks, Together): 262k context,
tool use + thinking + vision, default reasoninghigh. - Meta Muse Glimmer 30B (Fireworks, Together): multimodal agent model,
131k context, schema-based tool calling, default reasoninghigh. - DeepSeek V4 Pro Latest and Qwen3.8 27B (CrofAI).
- Model
default_reasoningextended withxhigh,max,ultra.
🧾 Documentation (PR #47 by @fy17ohhh)
- Custom LLM provider guide with Ollama / llama.cpp / LM Studio schema,
remote SSE MCP example, and background MCP discovery notes.
⚡ Performance & Startup
- Startup time optimized: version-check wait reduced from 5s → 2s, and
httpcore,httpcore2,httpx,httpx2loggers silenced toERROR. RemoteAgentis now lazily imported via module__getattr__, dropping
heavy A2A imports from the startup path.- MCP discovery moved to durable, manager-owned background threads (with their
own event loop) that survive command-loop closure; built-in tools sync
immediately, MCP tools final-sync on the first message with a bounded
30-second fail-open wait. A timeout never cancels the underlying discovery. - Per-agent discovery deduplication (
concurrent.futures.Future) and a stale
completion guard so a completed background worker can never repopulate a
deactivated agent.
🐛 Bug Fixes
- Token stats:
ConversationUsage.add_turnno longer accumulates
per-turn input/output/cached tokens into a running counter — turns are now
recorded correctly while totals/cost still accrue. /debugno longer mutates messages: debug output deep-copies chat and
streamed histories so debug can't affect real message state.- Debug JSON rendering:
markup=Falseprevents Rich markup from hiding
message content. - Agent history behavior: switching agents only inherits the previous
agent's history when the new agent has none of its own, and no longer
resets an agent already involved in a conversation. - Remote agent state reset is now only applied when the target agent is
actually aRemoteAgent(lazy imported), preserving conversation manager
behavior for local agents. - MCP session lifecycle: fixed rework replaces brittle setup timeouts
with a strict reverse-order scope teardown (session → transport → HTTP
client) that closes every resource exactly once; teardown failures and
cancellation never mask the primary error (fixes a historical OAuth/AnyIO
hang). - MCP v2 field compat: pagination uses
next_cursor, resources use
mime_type, tools useinput_schema, resource links use plain string URIs;
Errortool results now wrapMCPErrormessages. - OAuth: callback captures RFC 9207
ississuer and returns
AuthorizationCodeResult, while legacy stored client info (no issuer)
remains loadable.
⚙️ Upgrades & Breaking Changes
mcp1.27.1 → 2.0.0 (MCP v2 spec): SDK split intomcp+mcp-types,
API renames above, OAuthAuthorizationCodeResultsemantics.httpx→httpx2(+httpcore2): all internal HTTP clients (A2A
downloads, remote agent streaming, OAuth, usage APIs, image fetch, web
extraction) migrated.⚠️ Accepted residual risk:a2a-sdkstill types and
catcheshttpxexceptions, so httpx2 transport errors may bypass the SDK's
A2AClientErrorconversion untila2a-sdkadopts httpx2 (documented in
TestRemoteAgentHttpClientBoundary).streaming_serversemantics documented precisely: URLs ending in/sse
use the legacy SSE transport; any other URL uses Streamable HTTP.
🧰 Internal Refactors
- LLM ownership lifecycle extracted into
AgentLLMLifecycle
(dedicated_llm,is_service_owned,close_superseded,release_llm,
ensure_reasoning_isolated,apply_reasoning, sync + async replacements).
ServiceManagergainedclone_service,get_service_for_selection,
close_service, and draining of pending close tasks at shutdown with
exactly-once per-service dedup. - Collaborator extraction from
LocalAgentinto
AgentMemoryCoordinator(memory parsing/storage) and
AgentMessageFormatter(assistant/tool formatting), mirroring the existing
AgentContextManager/AgentToolRegistrarpattern; public wrappers keep
every caller unchanged. AgentManager.deregister_agentnow releases a removed LocalAgent's owned
dedicated LLM service (exactly once, when not cached and not referenced by
a remaining agent);shutdowndrains all dedicated services.- Debug message arg preview now shows both start and end of long values
(...original[-25:]) for more useful traces.
👏 Contributors
We'd like to thank everyone who contributed to this release:
- @daltonnyx (Quy Truong) — author of most of v0.21.0: A2A chat UI, reasoning-effort controls, model selection rework, MCP v2 + httpx2 upgrades, performance work, and bug fixes.
- @fy17ohhh — full-text conversation search with match previews (#48), and custom provider documentation (#47).
Your time and effort make AgentCrew better for everyone. 💙
Full changelog: see the commit history