An agent loop is the difference between asking AI for help and waking up to finished work. Most people never build one because a hundred iterations on a frontier model costs real money.
Inside: the loop pattern explained in one diagram, two exact setups (Claude Code and raw API), and the cache math that makes K3 the loop machine.
Your first loop runs tonight at about $0.39 per turn.
Here's the full setup ๐
Before we dive in, I share daily notes on AI & vibe coding in my Telegram channel: https://t.me/zodchixquant ๐ง

What a loop actually is
Strip the hype and a loop is four steps on repeat:
1GOAL โ ATTEMPT โ CHECK โ (better? keep : retry)2 โ__________________________|
- Goal: a measurable finish line, not a vibe. "All tests pass", "page loads under 1s", "score above 90"
- Attempt: the model does one unit of work toward it
- Check: something verifies the result against the goal. A test suite, a linter, a second model
- Repeat: feed the check result back, go again, stop when the goal is met or the budget dies
That's it. Everything else (memory, subagents, overnight runs) is decoration on this cycle.
Why K3 specifically: the loop economics
Loops re-read the same context every turn: the codebase, the goal, the history. On most models you pay full price for that repetition. On K3 you don't:
1Turn cost = fresh_tokens ร $3/M + cached_tokens ร $0.30/M23Real shape (800K stable context + 50K fresh per turn):4K3: $0.24 + $0.15 = $0.39/turn5Fable 5: 850K ร $10/M = $8.50/turn
A 50-turn overnight loop: about $20 on K3, about $425 on Fable 5. That's not a discount, that's the difference between "let it run" and "watch it like a hawk".
The one rule: keep your stable context as an identical prefix every turn, task at the end, so the cache actually hits.

Setup A: Claude Code (the 5-minute path)
If you live in Claude Code, loops are built in and K3 slots underneath via Moonshot's official config:
1export ANTHROPIC_BASE_URL=https://api.moonshot.ai/anthropic2export ANTHROPIC_AUTH_TOKEN=${YOUR_MOONSHOT_API_KEY}3export ANTHROPIC_MODEL=kimi-k34export ANTHROPIC_DEFAULT_OPUS_MODEL=kimi-k35export ANTHROPIC_DEFAULT_SONNET_MODEL=kimi-k36export ANTHROPIC_DEFAULT_HAIKU_MODEL=kimi-k37export CLAUDE_CODE_SUBAGENT_MODEL=kimi-k38export ENABLE_TOOL_SEARCH=false9export CLAUDE_CODE_AUTO_COMPACT_WINDOW=104857610claude
Then the loop is two commands:
- /goal sets the finish line: "all tests in tests/ pass and coverage stays above 80%". Claude Code keeps working toward it instead of stopping at the first answer
- /loop makes it recurring: the session re-runs on a schedule or until the goal holds
Confirm you're on K3 via /status (the /model menu won't show it). The 1M auto-compact window in the config means long loops compact rarely, which keeps iteration history alive.
Setup B: the raw API loop (full control)
For loops outside Claude Code, here's a complete minimal loop, OpenAI-compatible:
1from openai import OpenAI23client = OpenAI(4 api_key=MOONSHOT_API_KEY,5 base_url="https://api.moonshot.ai/v1",6)78# Stable prefix: identical every turn = cache hits at $0.30/M9STABLE = f"""You are a coding agent in a loop.10GOAL: make all tests pass in the project below.11PROJECT:12{project_dump}13RULES:14- One focused change per turn15- Explain what you changed and why in 2 lines16- If tests pass, reply exactly: GOAL_REACHED17"""1819history = []20MAX_TURNS = 302122for turn in range(MAX_TURNS):23 result = run_tests() # your check: pytest, npm test, etc.24 if result.passed:25 print(f"Done in {turn} turns")26 break2728 response = client.chat.completions.create(29 model="kimi-k3",30 messages=[31 {"role": "system", "content": STABLE},32 *history[-6:], # last 3 exchanges, capped33 {"role": "user", "content":34 f"Turn {turn}. Test output:\n{result.output}\n"35 f"Fix the next failure."},36 ],37 )38 change = response.choices[0].message.content39 apply_change(change) # write the edit, commit to a branch40 history += [41 {"role": "user", "content": f"Turn {turn} test output given"},42 {"role": "assistant", "content": change},43 ]
Three load-bearing details:
- The check is code, not vibes. run_tests() decides progress, the model never grades itself
- History is capped. Last 3 exchanges only; the stable prefix carries the durable context and stays cache-friendly
- Every change goes to a branch. The loop can be wrong 10 times as long as main never sees it
Guardrails before you walk away
- Budget stop: count tokens per turn, kill the loop at a dollar cap. MAX_TURNS is not enough, one bloated turn can out-eat ten normal ones
- Progress stop: if the same test fails 3 turns in a row, halt and flag. Loops that can't converge burn money politely
- One K3 catch: reasoning runs at max-only for now, so every turn carries full thinking output at $15/M. Keep turns focused, one failure per turn, and the output side stays sane
Common mistakes
- Vague goals. "Improve the code" loops forever. A loop is only as good as its finish line is checkable
- Letting the model self-grade. "Looks correct to me" is how loops ship garbage. The checker must be external: tests, linter, or a second model with a rubric
- Breaking the cache. Timestamps, random IDs, or reordered files in your prefix mean every turn bills at $3/M instead of $0.30. Identical means identical
- No branch discipline. An unsupervised loop with write access to main is a horror story with extra steps
- Starting with overnight runs. Run your first loops while watching, 10-15 turns. Earn the trust before you sleep on it
The 15-minute setup
- Grab a Moonshot API key, top up inside the 10-30% bonus window, live to August 11 (3 min)
- Pick Setup A or B and wire it (5 min)
- Write one checkable goal for a real small task: a failing test, a lint pass (2 min)
- Run 10 supervised turns, watch the check drive the work (4 min)
- Note the cost. Then decide how big the next loop gets (1 min)
The loop is the oldest idea in programming applied to the newest tool. K3 just made it cheap enough to actually use.
Thanks for reading!
I share daily notes on AI & vibe coding in my Telegram channel: https://t.me/zodchixquant ๐ง






