Skip to content

Releases: fischerf/aar

v0.3.1

11 Apr 09:58

Choose a tag to compare

Aar v0.3.1 — Better UX, Customizable Hotkeys, More Configs

January 2025

What's New

🎨 Proof of Concept

  • Shadow Branching Protocol — Idea as project rulesmd added config/rules/ideas/rules.md for a full automated time travel git workflow with branching!!!

🎨 User Experience Enhancements

  • Multiline Input — Write complex prompts across multiple lines. Use Enter for new lines, Ctrl+S to send.
  • Collapsible Think Panel — Reasoning output now appears in a hideable sidepanel. Toggle with Ctrl+T to maximize workspace.

⌨️ Keyboard Control

  • Customizable Keybindings — Remap shortcuts via external config files without code changes.
  • Ctrl+S Send — Quick alternative to Enter for sending messages in the TUI.

⚙️ Configuration & Providers

  • OmniCoder Preset — New config_omnicoder.json for code-focused workflows with Ollama.
  • Enhanced System Prompt — Improved minimal ReAct loop in config/rules/rules.md with clearer action rules and failure recovery.
  • Config Documentation — Completely rewritten config/README.md with quick start, examples, and troubleshooting.

📺 Documentation

  • Better Examples — OS-specific setup instructions and use-case walkthroughs.

🔧 Under the Hood

  • Error-Isolated Event Dispatch — Tool and provider failures now emit events for better observability.
  • Unified Logging — Consistent logging across CLI, TUI, and web transports.

🐛 Fixes

  • Fixed approval modal theme color handling
  • Corrected token display during streaming
  • Improved focus handling in modal transitions

✅ Compatibility

Fully backward-compatible with v0.3.0. No breaking changes. Upgrade freely.

📖 Learn More

🙌 Thanks

Special thanks to everyone who provided feedback on TUI usability. Your input shaped this release!

Full Changelog: v0.3.0...v0.3.1

v0.3.0

08 Apr 21:39

Choose a tag to compare

Release Notes — v0.3.0

Released: 2026
Tag: v0.3.0
Previous: v0.2.1


Highlights

This release is a major feature drop. The two biggest gaps versus v0.2.1 — no streaming and no reliability safeguards — are both closed. On top of that: full multimodal input, a rich theming system, a new full-screen TUI powered by Textual, automatic context management, parallel tool execution, and a completely restructured documentation suite.

69 files changed, 11 559 insertions, 1 266 deletions.
Tests: 490 (up from ~310 at v0.2.1).


Core Loop

Token-level streaming

Set streaming = true in aar.json (or AgentConfig.streaming = True) to switch from
batch-response mode to token-level streaming. The loop streams deltas from the provider and emits
a StreamChunk event for every token, so TUI / web consumers can display output as it generates.

{
  "streaming": true
}

All three providers (Anthropic, OpenAI, Ollama) expose the new Provider.stream() async-generator
protocol. The loop falls back to batch mode when a provider does not support it.

Retry with exponential backoff

Provider failures on recoverable errors (rate limits, timeouts, transient network issues) are now
retried automatically instead of immediately setting AgentState.ERROR.

{
  "max_retries": 3
}

Retry schedule: 1 s → 2 s → 4 s (2^(attempt−1)). Non-recoverable errors (auth failures, bad
requests) are never retried. The --log-level DEBUG flag shows each retry attempt.

Automatic context management

Configure a token budget to prevent silent failures when sessions approach the model's context
limit. The sliding_window strategy drops the oldest messages that exceed the budget.

{
  "context_window": 8192,
  "context_strategy": "sliding_window"
}

Token counting uses a fast heuristic (~4 chars/token). Set context_window = 0 (default) to
disable and preserve the previous unbounded behavior.

Parallel tool execution

When the model returns multiple tool calls in a single turn, they are now executed concurrently
with asyncio.gather(). This is the default behavior and requires no configuration. Set
parallel=False on ToolExecutor.execute() to force sequential execution.

Tool argument validation

ToolExecutor now validates tool call arguments against each tool's input_schema using
jsonschema before dispatching. Malformed LLM responses produce a structured ToolResult error
instead of a cryptic Python traceback.

Multiple event callbacks (sync + async)

Agent.on_event() previously accepted only a single callback. It now maintains a list; every
registered callback fires in registration order. Both synchronous and async callables are
accepted — async callbacks are scheduled with asyncio.ensure_future().

agent.on_event(log_to_disk)        # sync
agent.on_event(push_to_webhook)    # async def

State machine fixes

AgentState.TIMED_OUT and AgentState.MAX_STEPS are now set correctly when the loop exits for
those reasons. Previously both fell back to AgentState.ERROR.


Multimodal Input

A new agent/core/multimodal.py module defines typed content blocks for mixed-media messages.
Session.add_user_message() and Agent.run() / Agent.chat() now accept either a plain string
or a list of content blocks.

from agent.core.events import ImageURLBlock, ImageURL, TextBlock

response = await agent.chat([
    TextBlock(text="What is in this image?"),
    ImageURLBlock(image_url=ImageURL(url="https://example.com/photo.jpg")),
])

New content block types (all Pydantic models, discriminated on type):

Block Type tag Notes
TextBlock "text" Plain text
ImageURLBlock "image_url" HTTP URL or data: URI; optional detail hint for OpenAI
AudioBlock "audio" URL or base-64 audio; format auto-detected
VideoBlock "video" Prepared — not yet implemented at provider level

Provider support:

Provider Image Audio Video
Anthropic
OpenAI
Ollama ✅ (vision models)

UserMessage.parts carries the full block list for providers; UserMessage.content holds a
plain-text summary for logging and display. The is_multimodal property is True when parts
is non-empty.


New Events

Event When emitted
StreamChunk Every token delta during streaming (text, reasoning_text, finished)
ReasoningBlock Model thinking / chain-of-thought content (Ollama 0.20+, Anthropic extended thinking)

EventType.STREAM_CHUNK is the new enum value.


Configuration

New fields on AgentConfig:

Field Type Default Description
streaming bool False Enable token-level streaming
max_retries int 3 Max retry attempts for recoverable provider errors
context_window int 0 Token budget (0 = disabled)
context_strategy str "sliding_window" Context trimming strategy
response_format str "" "" | "json" | "json_schema"
json_schema dict {} Schema used when response_format = "json_schema"
shell_path str "" Override the shell executable for tool calls
project_rules_dir Path .agent Directory for rules.md project instructions
log_level str "WARNING" Python logging level
tui TUIConfig TUI appearance settings (see Themes)

The system_prompt is now built automatically from shell_path and project_rules_dir if not
explicitly provided; override it by setting system_prompt directly.


Themes

A new agent/transports/themes/ package introduces a full theming system for both TUI modes.

Four built-in themes:

Name Description
bernstein Dark blue / gold — the new default
classic Green-on-dark terminal classic
decker High-contrast amber / charcoal
sleek Minimal monochrome

Configure the theme in aar.json:

{
  "tui": {
    "theme": "decker"
  }
}

Hot-switch at runtime with /theme <name> in either TUI mode. Custom themes can be defined in a
JSON file and registered with ThemeRegistry. The Theme and TUIConfig models are fully typed
Pydantic models in agent/transports/themes/models.py.


TUI — Full-screen Fixed Mode (aar tui --fixed)

A brand-new full-screen terminal UI built on Textual,
replacing the earlier experimental prototype.

aar tui --fixed

Features:

  • Full-screen layout with a dedicated header bar, scrollable chat body, and sticky input bar
  • Mouse support (click, scroll)
  • Keyboard shortcuts (Ctrl+C to cancel a running turn, Ctrl+D to quit)
  • Live token streaming — output appears word-by-word
  • Thinking / reasoning blocks rendered as collapsible sections
  • Tool call blocks: name, arguments, result, timing
  • Selectable chat blocks — click to copy content
  • Full theme support; hot-switch at runtime
  • Non-blocking — the UI stays responsive while the agent runs

The implementation is modularized under agent/transports/tui_widgets/:

Module Contents
bars.py HeaderBar, status indicator, model/session pill
blocks.py AssistantBlock, ToolBlock, ThinkingBlock, UserBlock
chat_body.py Scrollable chat container, auto-scroll-to-bottom
input.py HistoryInput — multi-line input with command history

Shared formatting helpers live in agent/transports/tui_utils/formatting.py and are used by
both the Rich inline TUI and the Textual fixed TUI.


TUI — Rich Inline Mode (aar tui)

  • Themes applied to all Rich renderables
  • Non-blocking event loop — UI stays responsive during generation
  • Copy/paste improved on Windows
  • /status no longer queries the LLM when no session has started
  • Ollama reasoning (thinking) blocks displayed correctly
  • Layout polish: separator styles, button sizing, input field theming

Providers

Streaming protocol

All providers implement the new async def stream(...) async generator that yields StreamDelta
objects. Provider.supports_streaming property lets the loop opt-in per provider.

Ollama

  • Thinking mode — pass supports_reasoning = true in provider extra to enable Ollama 0.20+
    think mode. Reasoning content is emitted as a ReasoningBlock event.
  • Structured outputresponse_format = "json" sets format: "json"; "json_schema" passes
    the full schema via format: {...}.
  • Capability flags in extra: supports_vision, supports_audio, supports_tools,
    supports_reasoning.
  • Warning emitted when audio input is sent to an Ollama model (not supported as of v0.20).

Sample Ollama configs

Three ready-to-use config files are included in config/samples/:

File Model
config_gemma.json gemma4:e4b (vision, reasoning)
config_qwen.json qwen3.5:9b
config_deepseek.json deepseek-r1:8b (reasoning)

Session & Memory

JSONL schema versioning (SCHEMA_VERSION = 1)

Session files now include a schema_version header. Loading a session saved by a newer version
of aar raises a clear ValueError with an upgrade message instead of silently producing garbage.
Loading an older session logs a migration notice. This is the foundation for safe schema
evolution going forward.

Context trimming helpers

Two new public functions in agent.core.session:

  • estimate_token_count(messages) — fast heuristic token counter (~4 chars/token)
  • `trim_to_token_budge...
Read more

v0.2.1

02 Apr 22:59

Choose a tag to compare

What's Changed

  • markdown rule system added [system/global/local]
  • config system added for defaults and mcp_servers
  • system specific updated esp. safety
  • new commands

Full Changelog: v0.2.0...v0.2.1

v0.2.0 - Intial release

31 Mar 20:59

Choose a tag to compare

A lean, provider-agnostic agent framework with a thin core loop, typed event model, sandboxed tool execution, and pluggable transports. Aar stands for Adaptive Action & Reasoning.

Design goals

Thin core loop — the main execution path is small and readable at a glance
Typed event model — every message, tool call, and result is a typed, serializable event
Provider-agnostic — swap between Anthropic, OpenAI, and Ollama without changing agent code
Safe by default — path restrictions, command deny-lists, and approval gates built in
Modular transports — the same agent runs from CLI, TUI, web API, or embedded in your code
Persistent sessions — every run is saved as JSONL and resumable; long sessions can be compacted
Observable — every provider call and tool execution is timed; sessions carry a trace_id
Cancellable — cooperative (asyncio.Event) and hard (CancelledError) cancellation built in