Skip to content

DWIM-Driven Agentic Loop ​

Design for an indefinite agent loop where the LLM outputs terse intents and DWIM handles tool routing.

Philosophy ​

  • LLM makes decisions, not tool selections
  • DWIM interprets intent and routes to appropriate tools
  • No tool schemas in prompts - saves tokens, reduces coupling
  • Terse agent output - "view foo.py" not "please show me the structure"
  • Natural language for humans - same DWIM handles both

Architecture ​

┌──────────────────────────────────────────────────────┐
│                   AGENT LOOP                          │
├──────────────────────────────────────────────────────┤
│                                                       │
│  USER/LLM                                             │
│     │                                                 │
│     ▼                                                 │
│  "view foo.py"  ─or─  "show me the structure"        │
│     │                                                 │
│     ▼                                                 │
│  DWIM PARSER                                          │
│     ├─ Extract verb: view, edit, analyze             │
│     ├─ Extract target: file path, symbol, error desc │
│     └─ Route to tool with confidence score           │
│     │                                                 │
│     ▼                                                 │
│  TOOL EXECUTOR                                        │
│     ├─ Core Primitives (view, edit, analyze)         │
│     ├─ MCP servers (external capabilities)           │
│     └─ LLM (when tool needs generated content)       │
│     │                                                 │
│     ▼                                                 │
│  RESULT → fed back to LLM                            │
│     │                                                 │
│     ▼                                                 │
│  LLM → next intent ─or─ "done"                       │
│                                                       │
└──────────────────────────────────────────────────────┘

Agent Output Format ​

Terse, token-efficient. Verb + target(s):

view src/normalize/agent_loop.py
view src/normalize/agent_loop.py/Patch
analyze --complexity
edit -f patches.py "add type check for anchor"
done

No prose, no "I will now...", just action.

DWIM Responsibilities ​

  1. Verb extraction - identify action: view, edit, analyze, done
  2. Target extraction - parse file paths, symbol names, options
  3. Tool routing - map intent to one of 3 core primitives
  4. Confidence scoring - know when to ask for clarification
  5. Parameter construction - build tool call from extracted parts

Integration Points ​

Existing Infrastructure ​

  • normalize.dwim - has resolve_core_primitive(), simple alias matching
  • normalize.session - tracks tool calls, file changes, LLM usage
  • normalize.agent_loop - has AgentLoopRunner, executors, metrics
  • litellm - unified LLM access

What Needs Building ​

  1. Intent parser - extract verb + targets from terse commands
  2. Main loop - iterate: LLM → DWIM → execute → result → LLM
  3. Completion detection - recognize "done" signal
  4. Context management - what to feed back to LLM (truncation, summarization)

Example Flow ​

User: "Fix the type error in Patch.apply"

LLM: view src/normalize/patches.py
     → Routes to view command (Rust CLI)
     → Returns: class Patch, def apply(...) skeleton

LLM: view src/normalize/patches.py/Patch/apply
     → Routes to view with symbol path
     → Returns: full function source

LLM: edit -f patches.py "add type check for anchor parameter"
     → Routes to edit command
     → Applies fix via structural editing

LLM: analyze --security
     → Routes to analyze command
     → Returns: no issues found

LLM: done
     → Loop terminates

Token Efficiency ​

Compared to tool-schema approach:

ApproachTokens/turnNotes
OpenAI function calling~500-2000Full schemas every request
Claude Code XML~200-500Tool blocks + formatting
DWIM terse~10-50Just "view foo.py"

90%+ token reduction for tool selection.

Context Model: Hierarchical Path ​

The agent does NOT accumulate conversation history. Context is structured as a path from root task to current leaf, with optional attachments.

Core Structure ​

Task: Fix auth bug
  → Find failure point ✓ (token expires during refresh)
  → Implement fix
    → [now] Patching refresh_token()

[note: refresh_token() is called from 3 places | expires: on_done]

Design Principles ​

  • Context-excluded by default: Start lean, pull what's needed
  • Path, not history: Chain of refinements, not transcript
  • Levels emerge, not predefined: Arbitrary depth, task dictates structure
  • Recursive breakdown is fundamental: Agent decomposes until leaf is actionable

Path Components ​

Each node in the path:

  • goal: What this step aims to do
  • status: pending | active | done | blocked
  • summary: One-line result (when done)
  • description: Expandable detail (on demand)
  • children: Subtasks (if decomposed)

Attachments ​

Standalone notes that travel with context:

  • content: The note itself
  • condition: When to expire (on_done, after:N_turns, until:pattern_found, manual)
  • scope: Which subtree it applies to
note("refresh_token calls: auth.py:45, session.py:120, api.py:89", expires="on_done")
note("avoid changing public API", expires="manual")

Prompt Structure ​

Each turn:

[system: terse agent role]
[path: Task → Subtask → Current step]
[notes: active attachments]
[last_result: preview + id:0042]
[action?]

~300 tokens typical, scales with path depth not turn count.

State is External ​

  • Path nodes: TaskTree structure
  • Full outputs: EphemeralCache (by ID)
  • Notes: Attachment store with TTL
  • Findings: Working memory (compact)

Open Questions ​

  1. Ambiguity handling - when DWIM confidence is low, ask LLM to clarify or just pick best?
  2. Error recovery - tool fails, how does LLM know? Structured error format?
  3. Multi-step intents - "fix and validate" in one line?
  4. Decomposition trigger - when does a task become subtasks? LLM decides? Heuristic?
  • docs/dwim-architecture.md - DWIM internals
  • docs/hybrid-loops.md - CompositeToolExecutor for multi-source tools
  • docs/philosophy.md - minimize LLM usage, structure over text