Skip to content

v0.21.0

Choose a tag to compare

@daltonnyx daltonnyx released this 24 Aug 15:52
· 7 commits to main since this release

✨ 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 A2A contextId/taskId continuity.
  • Agent selector per turn, input-required continuation 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 sessionStorage only (never
    persisted); public UI routes stay public while protected routes require a
    Bearer token. The public /_a2a-ui/config endpoint never leaks the key.
  • New public /agents route 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_effort field in agent configs (agents.toml),
    editable from the GUI agent editor.
  • /think slash command now accepts reasoning levels; the legacy numeric
    thinking budget still works.
  • Documented reasoning precedence: user switch (/think) > CLI > agent config

    model default. New reasoning_selection module 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
    .
  • /model force 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 reasoning high.
  • Meta Muse Glimmer 30B (Fireworks, Together): multimodal agent model,
    131k context, schema-based tool calling, default reasoning high.
  • DeepSeek V4 Pro Latest and Qwen3.8 27B (CrofAI).
  • Model default_reasoning extended with xhigh, 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, httpx2 loggers silenced to ERROR.
  • RemoteAgent is 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_turn no longer accumulates
    per-turn input/output/cached tokens into a running counter — turns are now
    recorded correctly while totals/cost still accrue.
  • /debug no longer mutates messages: debug output deep-copies chat and
    streamed histories so debug can't affect real message state.
  • Debug JSON rendering: markup=False prevents 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 a RemoteAgent (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 use input_schema, resource links use plain string URIs;
    Error tool results now wrap MCPError messages.
  • OAuth: callback captures RFC 9207 iss issuer and returns
    AuthorizationCodeResult, while legacy stored client info (no issuer)
    remains loadable.

⚙️ Upgrades & Breaking Changes

  • mcp 1.27.1 → 2.0.0 (MCP v2 spec): SDK split into mcp + mcp-types,
    API renames above, OAuth AuthorizationCodeResult semantics.
  • httpxhttpx2 (+ httpcore2): all internal HTTP clients (A2A
    downloads, remote agent streaming, OAuth, usage APIs, image fetch, web
    extraction) migrated. ⚠️ Accepted residual risk: a2a-sdk still types and
    catches httpx exceptions, so httpx2 transport errors may bypass the SDK's
    A2AClientError conversion until a2a-sdk adopts httpx2 (documented in
    TestRemoteAgentHttpClientBoundary).
  • streaming_server semantics 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).
    ServiceManager gained clone_service, get_service_for_selection,
    close_service, and draining of pending close tasks at shutdown with
    exactly-once per-service dedup.
  • Collaborator extraction from LocalAgent into
    AgentMemoryCoordinator (memory parsing/storage) and
    AgentMessageFormatter (assistant/tool formatting), mirroring the existing
    AgentContextManager / AgentToolRegistrar pattern; public wrappers keep
    every caller unchanged.
  • AgentManager.deregister_agent now releases a removed LocalAgent's owned
    dedicated LLM service (exactly once, when not cached and not referenced by
    a remaining agent); shutdown drains 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