Execution Engine
Each request runs the main loop in exec.Execute() for up to 128 iterations. Each iteration:
- Assemble messages:
SystemPrompts+OldHistories+UserInput+ToolHistories - Call
Agent.Send()on the chosen provider - Parse
tool_callsfrom the response - Dispatch the tool calls through
toolCall.go(three-pass concurrency, see below) - Append results to
ToolHistories - Stop when no
tool_callsremain or the iteration limit is hit
There is no inter-round delay — rate-limit protection comes from provider round-trip latency, per-model cooldown, and per-tool timeouts.
Three-pass tool concurrency
toolCall.go splits each round's tool calls into three serial passes; only Pass 2 fans out:
| Pass | Mode | Work |
|---|---|---|
| 1 — pre-flight | Serial | Duplicate-call dedupe (tool|args hash), stub-tool short-circuit, confirm gate, JSON-schema validation |
| 2 — execute | Concurrent for IsConcurrent-tagged tools; serial otherwise |
tools.Execute |
| 3 — commit | Serial | Land sessionData.Tools and ToolHistories, update the dedupe map, emit EventToolResult |
Concurrent-tagged tools: read_files, list_files, glob_files, search_files, fetch_page, search_web, search_google_news, send_http_request, download_file, transcribe_media, calculate, invoke_subagent, list_subagent_sessions, search_chat_history, search_error_history, read_error, remember_error, list_rag, search_rag, list_chatbot, list_tools, search_tools, list_schedule, list_revisions, reasoning_guide, write_skill, write_tool. Write-class file tools, run_command, interactive tools, api_* / script_* / ext_*, and MCP tools always run serially.
Dedupe is per run, not per session: a repeated tool|args pair returns the earlier result instead of executing again, and any write tool invalidates the read_files entries covering the paths it touched. A separate 30-minute result cache in ToriiDB covers fetch_page, search_web, and search_google_news only.
Pending registry
internal/runtime/pending.go is the prefix-routed confirm/ask listener registry shared by the main agent and any in-process subagents. Producers (toolCall confirm, ask_user handler, store_secret handler) call Ask(ctx, req) and block on a per-entry buffered=1 reply channel; each runtime registers a listener via pending.RegisterListener(prefix) (TUI/CLI use "" to match all, the Telegram daemon listener uses "tg-") and only claims matching entries through PickNextFor(prefix). ctx cancellation removes the entry so a stale producer never wastes a human interaction.
The gate pending.HasListener(sessionID) checks whether a listener with a matching prefix is registered for that session. This replaces the old global pending.Active atomic.Bool so Telegram, Discord, and CLI confirm flows can run side by side without blocking each other.
Send failure handling
Agent.Send() failures escalate instead of retrying blindly:
| Failure | Behavior |
|---|---|
| Timeout | Retry the same model up to MaxSendTimeoutRetries (3), spaced by SendTimeoutRetryInterval |
| Rate limit / upstream status the cooldown rules recognize | Register a 30-minute cooldown on that model, then switch to the next fallback |
| Context-length exceeded | Trim the oldest exchange (compact.TrimFallback) and resend; abort only when nothing is left to trim |
| Any other error | Switch to the next fallback model; abort when no healthy fallback remains |
Switching models clears ToolHistories (or applies compact.RawToolFallback), resets the dedupe map, and restarts the counters — a fresh model never inherits the failed model's partial state.
Cross-turn workdir reset
Each new user message rebuilds the Executor and resets data.WorkDir to the process cwd via os.Getwd() — cd-mutated workdir does not persist across turns. Two guardrails prevent the LLM from inferring stale workdir from history:
- L1 (system prompt) —
Work directory: {{.WorkPath}}line plus an explicit reminder that priorcdtext is from older turns - L2 (per-message) — Every user message is wrapped with a metadata header containing the current timestamp and working directory; the workDir line is the strongest anchor and overrides any history recency bias
The TUI strips the wrapper visually via stripUserMetaHeader; the LLM still receives it verbatim.
[!NOTE] This document was auto-generated by Claude after reading the full source code.