Skip to content

ExAgent v2.2.0

Choose a tag to compare

@kukapu kukapu released this 12 Oct 21:55
· 5 commits to main since this release

ExAgent 2.2.0 adds model fallback with retries, prompt caching, multimodal prompts and a final answer at the step limit, and refreshes ReqLLM to 1.28. It is additive: agents and models that do not use the new options behave as in 2.1.

Retry and fall back to another model

primary = ExAgent.Models.ReqLLM.new(primary_options ++ [foreign_history: :portable])
backup = ExAgent.Models.ReqLLM.new(backup_options ++ [foreign_history: :portable])
agent = ExAgent.new(model: ExAgent.Models.Fallback.new(models: [primary, backup]), tools: tools)
  • Retries HTTP 408/429/5xx/529 without output, with exponential backoff and jitter; connection failures only with retry_transport: true.
  • Each attempt keeps ModelSettings.timeout; the run deadline (new ModelRequestParameters.deadline) bounds all attempts. Streams retry only before their first event.
  • One admitted request per model call; every retry emits [:exagent, :model, :retry] telemetry.
  • foreign_history: :portable sends another model's history as plain text and tool calls, so the backup can continue the conversation.

Prompt caching

ExAgent.Models.ReqLLM option prompt_cache: cache_control breakpoints on OpenRouter (true or [ttl: "5m" | "1h"]) or a stable prompt_cache_key on OpenAI ([key: key]).

Images and documents in the prompt

ExAgent.run/3 accepts a list of content parts: text, image_url, image and file (PDF). Parts are validated and stored with string keys before any request.

Finish at the step limit

ExAgent.new(on_max_steps: :final) keeps tools declared but disallows calls in the last step and asks for a final answer. The instruction stays out of history.

Dependencies

  • req_llm ~> 1.28.0 (with llm_db 2026.10.3) and decimal 3.2.0. Update your application lock.
  • A sparse OpenAI-style usage map now keeps the reported counter instead of normalizing every counter to 0.

Verification

  • Offline suite: 2,305 of 2,306 passed, 28 excluded. The one failure was a test pinning the agent struct's fields, updated for on_max_steps; that file passes 5/5.
  • Live OpenRouter E2E, new features suite (fallback, caching, final step, PNG + PDF prompt): 4/4 with GPT-6-Luna and 4/4 with DeepSeek V4.1 Flash, including real cache hits on later turns.
  • GPT-6-Luna: smoke 23/23, skills 4/4, complex 4/4.
  • DeepSeek V4.1 Flash: smoke 22/23, skills 2/4 and complex 3/4. These failures come from the model's output: it doesn't copy a literal JSON value, returns reasoning with reasoning disabled, or skips a skill. ReqLLM's reasoning decoding is unchanged between 1.27 and 1.28.

Full details in the changelog.