# Stop Writing Tools > In August 2025 I built a personal assistant out of nine agents and around 40 tools. A year later I rebuilt it as a folder of instructions, a shell and a few CLIs, and ran both on the same requests. - URL: https://lokahq.github.io/tech-blog/stop-writing-tools/ - Type: Blog article - Authors: Petar Kalinovski (Machine Learning Engineer) - Published: 2026-10-20 - Tags: AI Agents, Claude Code, Strands Agents, Agent Architecture --- Tools are functions that let an LLM act as an agent. Calculating a sum or getting today’s date are the classic examples. They have been useful for a long time, and they’re still the most common way to build an agent. At Loka, most agentic projects use them. Say you’re building a personal assistant. You’d use an agent framework and build tools for it to use. To check your calendar. To add items to it. If there are too many tools, you might define “agents as tools” that work as subagents under an orchestrator. And this would work. I remember the first time I did it. It felt great. Giving your chatbot agency, so it can do more than just write text. ## Old Charon In August 2025, I built a personal assistant called Charon as my internship capstone project. It was a three-layer agent architecture: an orchestrator with two subagents, each with three subagents of its own. Nine agents and around 40 tools all in all (including the [GitHub MCP](https://github.com/github/github-mcp-server)). It managed my calendar, kept a journal, recommended newsfeeds, movies and books, and read me code (local and on GitHub). The reason for this many agents was that back then, models were far more likely to pick the wrong tool or mangle the input, especially the more tools you added. [![Old Charon's terminal welcome screen: a magenta ASCII drawing of the ferryman beside the word CHARON in block letters, the title The Ferryman's Assistant, and a double-bordered panel labelled Welcome Aboard.](https://lokahq.github.io/tech-blog/blog/stop-writing-tools/old-charon-banner.svg)](https://lokahq.github.io/tech-blog/blog/stop-writing-tools/old-charon-banner.svg) Old Charon’s welcome screen, rendered from the capstone’s own banner code. Click for full size. This behemoth genuinely worked. I used Sonnet 4, but because it was too expensive, sometimes I also used Devstral Medium (talk about a trip down memory lane), and when I tested it, it generally worked. And yet if you made this today and showed it to a serious person, you’d get laughed out of the room. _____&#xNAN;_project-charon/src/agents ``` big_boss_orchestrator ··········· journal · sleep tracking (4) ├── task_agent │ ├── file_search_agent ······· file_read · find_folder_from_name │ ├── google_calendar_agent ··· create_event · get_events │ └── github_agent ············ the GitHub MCP server └── home_agent ·················· create_event · get_events ├── books_agent ············· search · add · mark read · list (4) ├── movies_agent ············ OMDb · add · mark watched · list (4) └── recommender_agent ······· Substack + YouTube feeds (6) # every edge in this tree is a tool as well: eight *_agent_query tools # that pass a request down and a summary back up ``` Old Charon's nine agents, read from the capstone code. Tools are listed next to the agent that owns them. Every tool was a predetermined action. The model never had to do anything other than know which button to press (with the correct parameters, of course). That is what tools are for. They let a weak model look competent by having predetermined actions. They also make the model unable to do anything I hadn’t written a tool for. ## What changed The issue here is that recent models have been far from weak, starting almost an entire year ago. With the jump in capability that came with models like Opus 4.5, Claude Code and Codex finish hour-long tasks on their own. The idea that you need a hand-built tool that specifically does one job is wasteful at best and a limitation to the model at worst. So, how did we get here? Anthropic hasn’t published it, so this is my guess, but I think it’s a credible one. Think about your past experiences with Claude Code. Up until mid-2025, you would ask for a feature, and the model would begin building it. But the experience was a bit different than it is now. The user would intervene constantly. Either to suggest other improvements. Or to point out issues and problems. Now imagine you removed the human turns from this transcript and used it as training data. So, train the model to reach the end state by the path it took with the user. Just fully autonomously. Give negative rewards if it doesn’t reach the end state, or if it treats some of the intermediate steps as end goals, and that way you end up with a model with far better scores on long-horizon tasks. _____&#xNAN;_a session in mid-2025 ``` > add a session switcher to the CLI ⏺ Added a sessions command and a table > it crashes when there are no sessions ⏺ Handled the empty case, added a test > show the description next to each id ⏺ Added a description column. Done. ``` _____&#xNAN;_as training data? ``` task: add a session switcher to the CLI ⏺ Added a sessions command and a table ✗ stopping here is penalised > it crashes when there are no sessions ⏺ Handled the empty case, added a test > show the description next to each id ⏺ Added a description column. Done. ✓ end state reached: reward ``` My guess, not a published method: take a session where a person kept steering, strike out the person's turns, and reward only reaching the end state. ## What does “better” mean? I want to quantify this “the models got better” claim. More so than pointing out how today’s models can [break out of their eval environments](https://cdn.openai.com/pdf/67869394-cb91-4c12-888c-5cbd85c7814c/OpenAI-Hugging-Face%20Incident-Technical-Report.pdf) and take over parts of [Hugging Face](https://huggingface.co/blog/security-incident-july-2026) and OpenAI. Or how they can now solve [Millennium Prize problems](https://openai.com/index/navier-stokes-solution/). I think the following two benchmarks matter most for our use case. ### ARC-AGI ARC-AGI is a benchmark that tests the model’s ability to generalize by giving it novel puzzles. The idea is to see if the model can acquire a skill it hasn’t been trained on. When [OpenAI o3 scored 75.7% on ARC-AGI-1](https://arcprize.org/blog/oai-o3-pub-breakthrough) in December 2024 (87.5% with 172 times the compute), vs GPT-4o’s single digits, it was read across the field as a sign that scaling reasoning hadn’t hit a wall. Since then we have moved on to a harder successor, [ARC-AGI-2](https://arcprize.org/arc-agi/2). | | ARC-AGI-2 (%) | | -------------------- | ------------- | | Opus 4 (May '25) | 8.6 | | Sonnet 4.5 (Sep '25) | 13.6 | | Opus 4.5 (Nov '25) | 37.6 | | Sonnet 4.6 (Feb '26) | 60.4 | | Opus 4.6 (Feb '26) | 69.2 | | Opus 4.7 (Apr '26) | 75.8 | | Opus 4.8 (May '26) | 72.1 | | Fable 5 (Jun '26) | 89.2 | | Opus 5 (Jul '26) | 90.4 | View numeric chart data | Series | Category | ARC-AGI-2 score (%) | | --------- | -------------------- | ------------------- | | ARC-AGI-2 | Opus 4 (May '25) | 8.6% | | ARC-AGI-2 | Sonnet 4.5 (Sep '25) | 13.6% | | ARC-AGI-2 | Opus 4.5 (Nov '25) | 37.6% | | ARC-AGI-2 | Sonnet 4.6 (Feb '26) | 60.4% | | ARC-AGI-2 | Opus 4.6 (Feb '26) | 69.2% | | ARC-AGI-2 | Opus 4.7 (Apr '26) | 75.8% | | ARC-AGI-2 | Opus 4.8 (May '26) | 72.1% | | ARC-AGI-2 | Fable 5 (Jun '26) | 89.2% | | ARC-AGI-2 | Opus 5 (Jul '26) | 90.4% | ARC-AGI-2 scores for Claude models. The two jumps are highlighted: Opus 4.5 in November 2025, and [Fable 5](https://www.anthropic.com/news/claude-fable-5-mythos-5) in June 2026, the first Mythos-class model Anthropic released for general use. The dashed line marks the [Mythos Preview announcement](https://www.anthropic.com/glasswing) on April 7, 2026. Each score is the model's best setting on the [ARC Prize leaderboard](https://arcprize.org/leaderboard) (Semi-Private set): Opus 4.7, Fable 5 and Opus 5 at Max effort; Sonnet 4.6, Opus 4.6 and Opus 4.8 at High. You can see the November jump, from 13.6% to 37.6%. (You can probably see this new post-[Mythos](https://www.anthropic.com/glasswing) jump too.) So this benchmark tells us that the models have become much better at generalizing. Much better at understanding structures they have never seen (I am not even mentioning GPT-6 Astra and how it has [saturated ARC-AGI-3](https://arcprize.org/blog/astra)). So models have become much better at solving things not in the training data. Like being able to navigate your previously unseen CLI without needing tools for it. ### METR Long Horizon The [METR Long Horizon benchmark](https://arxiv.org/abs/2503.14499) measures how long a task, in human expert hours, the model can finish. [At the 50% horizon](https://metr.org/time-horizons/), Opus 4 (May 2025) is at 1.7 hours, Opus 4.5 (November) is at about 4.9 hours and Opus 4.6 (February 2026) at about 12 hours. Claude Mythos Preview (April 2026) came in at [“at least 16 hours”](https://x.com/METR_Evals/status/2052896621760004602), beyond what METR’s task suite can reliably measure (it saturated the benchmark). Since then, models like [Mythos 5.1](https://www.anthropic.com/claude-fable-and-mythos-5-1) and especially GPT-6 Astra (which has saturated a bunch of benchmarks) have become even more powerful. This is what I mean when I say models have become much more powerful since the summer of 2025. | | 50% time horizon ( h) | | ------------------------ | --------------------- | | Opus 4 (May '25) | 1.7 | | Opus 4.5 (Nov '25) | 4.9 | | Opus 4.6 (Feb '26) | 12 | | Mythos Preview (Apr '26) | 16 | View numeric chart data | Series | Category | Hours | | ---------------- | ------------------------ | ----- | | 50% time horizon | Opus 4 (May '25) | 1.7 h | | 50% time horizon | Opus 4.5 (Nov '25) | 4.9 h | | 50% time horizon | Opus 4.6 (Feb '26) | 12 h | | 50% time horizon | Mythos Preview (Apr '26) | 16 h | [METR 50% time horizon](https://metr.org/time-horizons/), in human expert hours. Mythos Preview's 16 hours is a [lower bound](https://x.com/METR_Evals/status/2052896621760004602): it went past what METR's task suite can reliably measure. [Anthropic’s own usage data](https://www.anthropic.com/research/measuring-agent-autonomy) shows that Claude Code’s longest turns (the 99.9th percentile) nearly doubled between October 2025 and January 2026, from under 25 minutes to over 45. Also, internally at Anthropic from August to December, Claude Code’s success rate on the hardest tasks doubled while human interventions per session fell from 5.4 to 3.3. _&#xNAN;_Before_&#xNAN;_After Longest Claude Code turns99.9th percentile, Oct 2025 → Jan 2026 <25 min → **>45 min** Success rate on the hardest tasksinternal, Aug → Dec 2025 1× → **2×** Human interventions per sessioninternal, Aug → Dec 2025 5.4 → **3.3** From Anthropic's [Measuring agent autonomy](https://www.anthropic.com/research/measuring-agent-autonomy). The success rate is only reported as a ratio, so its row shows it doubling. ## We don’t need that anymore The issues with forcing a competent model to follow a tool structure are plentiful. It can’t chain two tools without a round trip through its context. It can’t save an intermediate result to disk and come back to it. It can’t do anything other than what I anticipated. Everything it can do is predetermined by the person who wrote the tools. And everything has to be explained. And coded. _____&#xNAN;_old Charon, request 1 ``` > What's new from my Substacks and YouTube channels? Pick two. big_boss_orchestrator journal ×3└── home_agent get_events asked once └── recommender_agent asked 6 timesget_all_newsletters ×5get_all_monitored_youtube_channelsget_recent_posts_from_newsletter ×9get_recent_youtube_videos ×5 31 tool calls · 24 model calls · 99 s ⏺ My two picks from this week are both YouTube interviews: 1. Ezra Klein Show: "Jensen Huang Thinks A.I. Alarmism Has Gone Too Far" (1h47m, Sep 23). […] 2. The Rest Is Politics: Leading, "Can AI Stay Under Human Control?" with Mustafa Suleyman (1h04m, Sep 28). […] ``` _____&#xNAN;_new Charon, request 1 ``` > What's new from my Substacks and YouTube channels? Pick two. ⏺ Bash cat ~/Documents/Vault/Charon/follows.md; ls …/journal | tail -5 → the 5 newsletters and 5 channels I follow⏺ Bash for u in <5 feeds>; do curl -sL "$u/feed" -o …xml & done; for c in <5 channels>; do yt-dlp … & done; wait → blocked: inline loops need my approval⏺ Write /tmp/charon/fetch_follows.sh → the same loop, as a script⏺ Bash bash /tmp/charon/fetch_follows.sh → all 10 saved to /tmp/charon/feeds⏺ Write /tmp/charon/summarize_feeds.py⏺ Bash python3 /tmp/charon/summarize_feeds.py → this week's posts from every feed⏺ Write /tmp/charon/yt_dates.sh⏺ Bash bash /tmp/charon/yt_dates.sh → upload dates and lengths 8 tool calls · 9 model calls · 85 s ⏺ My two picks: First, Ezra Klein with Jensen Huang, "Jensen Huang Thinks A.I. Alarmism Has Gone Too Far", an hour and 47 minutes. […] Second, Dwarkesh with Sarah Paine, "Why wars are so difficult to end", 52 minutes. […] ``` Request 1 from the comparison below, on Opus 5.5. Old Charon's logs record tool names without arguments, so its calls are grouped by the agent that owns them. Both versions picked the same first episode. ## What the assistant would look like today I remade Charon the way I would make it today, to compare a year-old app with a brand-new one. The idea here is to replace every tool with a CLI, a curl from a public endpoint, or lastly just bash for reading and writing local files. The new Charon is a folder: _____&#xNAN;_charon ``` petar@loka:~/Documents/charon$ tree charon/ ├── AGENTS.md 44 # who Charon is, where my data lives, which CLIs to use ├── CLAUDE.md 2 # two lines: @AGENTS.md and my preferences file ├── .agent/skills/planning/ │ └── SKILL.md 45 # the scheduling and estimation playbook └── .claude/ └── settings.json 51 # the boundary ``` New Charon. The yellow numbers are line counts. AGENTS.md holds short instructions for what it can use: ```md - Calendar: `gcalcli` (timezone Europe/Skopje). `gcalcli agenda "today" "7 days from now" --tsv` for reading. `gcalcli add` to create events. Always confirm before creating, moving or deleting an event. - GitHub: `gh` (logged in as PetarKalinovski). - Books: Open Library, e.g. `curl -s 'https://openlibrary.org/search.json?title=piranesi&limit=3&fields=title,author_name,first_publish_year,number_of_pages_median,subject'` - Movies and shows: OMDb, `curl -s "https://www.omdbapi.com/?apikey=$OMDB_API_KEY&t=severance"` - Substack: every newsletter has an RSS feed at `/feed`. - YouTube: `yt-dlp --flat-playlist -I 1:5 --print '%(title)s | %(url)s' /videos` ``` That’s roughly 3,080 lines of agents, tools, prompts and schemas, replaced by 89 lines of instructions and a 51-line settings file, mostly permission rules. **Old Charon**3,080 lines __________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ **New Charon**140 lines ____________________________ _&#xNAN;_Old Charon: tools 1,211 · prompts 898 · agents 706 · schemas 265_&#xNAN;_New Charon: instructions (AGENTS.md + skill) 89 · settings.json 51 One square is ten lines. ## Comparing the two versions I ran both versions on the same four requests. First on Opus 5.5, then on Sonnet 5.5 (closer to what Charon was originally built for). The old one ran on [Strands](https://strandsagents.com/) through [OpenRouter](https://openrouter.ai/), while the new one ran in [Claude Code headless mode](https://code.claude.com/docs/en/headless) (`claude -p`). _&#xNAN;_Old Charon_&#xNAN;_New Charon Model calls Opus 5.5 72 → **31** Sonnet 5.5 53 → **29** Tool calls Opus 5.5 116 → **25** Sonnet 5.5 82 → **23** Time Opus 5.5 7.8 min → **3.1 min** Sonnet 5.5 4.4 min → **1.2 min** Cost Opus 5.5 ≈$7.35 → **$0.88** Sonnet 5.5 $0.45 → **$0.31** All four requests together. Each row is scaled to old Charon's total, so the solid dot shows how much of it new Charon needed. Sonnet 5.5 totals add up the mean of three runs per request. | | Old Charon · Opus 5.5 | New Charon · Opus 5.5 | Old Charon · Sonnet 5.5 | New Charon · Sonnet 5.5 | | ------------------- | --------------------- | --------------------- | ----------------------- | ----------------------- | | Feeds: pick two | 31 | 8 | 23 | 5 | | Book + sleep | 8 | 3 | 9 | 3 | | Two free hours | 11 | 5 | 19 | 8 | | Estimate + schedule | 66 | 9 | 31 | 7 | View numeric chart data | Series | Category | Tool calls | | ----------------------- | ------------------- | ---------- | | Old Charon · Opus 5.5 | Feeds: pick two | 31 | | Old Charon · Opus 5.5 | Book + sleep | 8 | | Old Charon · Opus 5.5 | Two free hours | 11 | | Old Charon · Opus 5.5 | Estimate + schedule | 66 | | New Charon · Opus 5.5 | Feeds: pick two | 8 | | New Charon · Opus 5.5 | Book + sleep | 3 | | New Charon · Opus 5.5 | Two free hours | 5 | | New Charon · Opus 5.5 | Estimate + schedule | 9 | | Old Charon · Sonnet 5.5 | Feeds: pick two | 23 | | Old Charon · Sonnet 5.5 | Book + sleep | 9 | | Old Charon · Sonnet 5.5 | Two free hours | 19 | | Old Charon · Sonnet 5.5 | Estimate + schedule | 31 | | New Charon · Sonnet 5.5 | Feeds: pick two | 5 | | New Charon · Sonnet 5.5 | Book + sleep | 3 | | New Charon · Sonnet 5.5 | Two free hours | 8 | | New Charon · Sonnet 5.5 | Estimate + schedule | 7 | Tool calls per request. Opus 5.5 is one run per request; Sonnet 5.5 is the mean of three. | | Old Charon · Opus 5.5 (s) | New Charon · Opus 5.5 (s) | Old Charon · Sonnet 5.5 (s) | New Charon · Sonnet 5.5 (s) | | ------------------- | ------------------------- | ------------------------- | --------------------------- | --------------------------- | | Feeds: pick two | 99 | 85 | 53 | 19 | | Book + sleep | 60 | 23 | 39 | 11 | | Two free hours | 75 | 31 | 51 | 17 | | Estimate + schedule | 236 | 45 | 118 | 26 | View numeric chart data | Series | Category | Seconds | | ----------------------- | ------------------- | ------- | | Old Charon · Opus 5.5 | Feeds: pick two | 99s | | Old Charon · Opus 5.5 | Book + sleep | 60s | | Old Charon · Opus 5.5 | Two free hours | 75s | | Old Charon · Opus 5.5 | Estimate + schedule | 236s | | New Charon · Opus 5.5 | Feeds: pick two | 85s | | New Charon · Opus 5.5 | Book + sleep | 23s | | New Charon · Opus 5.5 | Two free hours | 31s | | New Charon · Opus 5.5 | Estimate + schedule | 45s | | Old Charon · Sonnet 5.5 | Feeds: pick two | 53s | | Old Charon · Sonnet 5.5 | Book + sleep | 39s | | Old Charon · Sonnet 5.5 | Two free hours | 51s | | Old Charon · Sonnet 5.5 | Estimate + schedule | 118s | | New Charon · Sonnet 5.5 | Feeds: pick two | 19s | | New Charon · Sonnet 5.5 | Book + sleep | 11s | | New Charon · Sonnet 5.5 | Two free hours | 17s | | New Charon · Sonnet 5.5 | Estimate + schedule | 26s | Wall-clock time per request, in seconds. | | Old Charon · Opus 5.5 | New Charon · Opus 5.5 | | ------------------- | --------------------- | --------------------- | | Feeds: pick two | 1.89 | 0.23 | | Book + sleep | 0.24 | 0.14 | | Two free hours | 0.38 | 0.19 | | Estimate + schedule | 4.84 | 0.32 | View numeric chart data | Series | Category | USD | | --------------------- | ------------------- | ---- | | Old Charon · Opus 5.5 | Feeds: pick two | 1.89 | | Old Charon · Opus 5.5 | Book + sleep | 0.24 | | Old Charon · Opus 5.5 | Two free hours | 0.38 | | Old Charon · Opus 5.5 | Estimate + schedule | 4.84 | | New Charon · Opus 5.5 | Feeds: pick two | 0.23 | | New Charon · Opus 5.5 | Book + sleep | 0.14 | | New Charon · Opus 5.5 | Two free hours | 0.19 | | New Charon · Opus 5.5 | Estimate + schedule | 0.32 | Cost per request on Opus 5.5, in US dollars. Old Charon's costs are approximate. The full table below has the Sonnet 5.5 costs. Full results, old → new | Request | Model | Model calls | Tool calls | Time | Cost | | --------------------------------------------------------------------------------- | ---------- | ----------- | ---------- | ----------------- | --------------- | | What’s new from my Substacks and YouTube channels? Pick two. | Opus 5.5 | 24 → 9 | 31 → 8 | 99s → 85s | ≈$1.89 → $0.23 | | | Sonnet 5.5 | 13 → 6 | 23 → 5 | 53s → 19s | $0.145 → $0.062 | | Add Piranesi to my reading list. How did I sleep last week? | Opus 5.5 | 9 → 4 | 8 → 3 | 60s → 23s | ≈$0.24 → $0.14 | | | Sonnet 5.5 | 9 → 4 | 9 → 3 | 39s → 11s | $0.035 → $0.053 | | I have 2 hours free tonight. What should I do? | Opus 5.5 | 9 → 7 | 11 → 5 | 75s → 31s | ≈$0.38 → $0.19 | | | Sonnet 5.5 | 13 → 10 | 19 → 8 | 51s → 17s | $0.104 → $0.098 | | How long will a session viewer for project-charon take, and when can I fit it in? | Opus 5.5 | 30 → 11 | 66 → 9 | 236s → 45s | ≈$4.84 → $0.32 | | | Sonnet 5.5 | 18 → 9 | 31 → 7 | 118s → 26s | $0.163 → $0.101 | | **Total** | Opus 5.5 | 72 → 31 | 116 → 25 | 7.8 min → 3.1 min | ≈$7.35 → $0.88 | | | Sonnet 5.5 | 53 → 29 | 82 → 23 | 4.4 min → 1.2 min | $0.45 → $0.31 | How the comparison was run - Old Charon is the August 2025 capstone code on Strands Agents, with all nine agents pointed at the same model through OpenRouter. New Charon runs in Claude Code’s headless mode (`claude -p --output-format stream-json`). - Opus 5.5 is one run per request. Sonnet 5.5 is three runs per request, and the table shows the mean. - Nobody approves anything in a headless run, so writes were refused on both sides: old Charon’s calendar inserts and GitHub write tools, and new Charon’s `ask` rules. - Model calls count every call across old Charon’s nine agents, and Claude Code’s turns for new Charon. Tool calls count every tool use, blocked ones included. - Old Charon’s Opus costs are approximate: the $8.60 OpenRouter bill for five runs (the four requests plus one rerun of the first) split by each run’s token-priced cost at $4 and $20 per million input and output tokens. Its Sonnet costs are token-priced at $2 and $10. - Claude Code’s first call in every run already carried about 20,000 input tokens (19.9k on Opus, 21.9k on Sonnet): its system prompt, tool definitions and Charon’s own instructions. - New Charon’s costs are what Claude Code reports, and they include prompt caching. Priced at the full input rate instead, new Charon would have cost about $2.42 on Opus (against $7.35) and $1.14 on Sonnet (against $0.45). Answer quality was comparable on both new and old Charon. But you can see old Charon had different issues. ### Issues with old Charon You can see the huge cost and latency margins here. But more than that, the issue is structural. In the fourth task, old Charon made 66 tool calls: 35 GitHub MCP calls (29 of them reading files) and 22 local read calls of the same repo, because the local agent and the GitHub agent read it separately. **Old Charon**66 tool calls ____________________________________________________________________________________________________________________________________ **New Charon**9 tool calls __________________ _&#xNAN;_GitHub MCP: read a file · 29 → 0_&#xNAN;_GitHub MCP: other · 6 → 0_&#xNAN;_Reading the repo locally · 22 → 2_&#xNAN;_Routing to another agent · 4 → 0_&#xNAN;_Calendar, journal and other · 5 → 4_&#xNAN;_Blocked by a permission check · 0 → 3 Every tool call in the fourth request on Opus 5.5, in the order they ran. Hover a square for the tool name. New Charon read the repo with two shell commands. The whole task was 9 tool calls instead of 66 (3 of them blocked by Claude Code’s permission checks), and it took a fifth of the time it took old Charon. This is one of the big recurring issues with structuring subagents as tools. Stuff gets constantly re-read. It is a fundamental problem in agents as tools. Subagents get sent what the orchestrator decides. A summary, or a description of the task. It almost invites this token waste because the system is set up to lose context. _____&#xNAN;_request 4, old Charon ``` you │ the whole conversation ▼ big_boss_orchestrator │ a task description ▼ task_agent ├──────────────────────────┐ │ a task description │ a task description ▼ ▼ file_search_agent github_agent 22 × file_read 29 × get_file_contents │ │ ▼ ▼ project-charon (local) project-charon (GitHub) └────── the same repo ─────┘ # neither agent knows what the other read, and the orchestrator # can't tell the GitHub agent to skip the repo ``` Each layer only gets what the layer above decided to send. The orchestrator has the conversation with the user, so it has full context on what the user asks. The subagent has the specialized tool results. But the orchestrator doesn’t know what the local files agent read, so it can’t tell the GitHub agent to skip the repo. There can also be a case where the subagent misinterprets instructions from the orchestrator. In any case, when an instruction from the orchestrator is unclear to the specialist, it can ask a clarifying question, or it can try to gain as much context as possible itself. And given the way models are post-trained, gathering as much information as possible is practically demanded of them. And it’s something we as users like. Maybe I can fix this one case by grouping the subagents differently. So instead of a GitHub and a local files agent, I make one repo-reader agent. But that only works because I have seen the overlap. Grouping them this way will most likely create the same problem in a different place. It will be a constant battle to make this way of scaffolding work, when in truth you probably don’t have to. It is the same problem as with the tools. It can’t do stuff you didn’t plan for. ### Better on old Charon The small requests were genuinely good on the old version too. And it was only slightly worse on the bigger requests. Also, because Claude Code starts every run with 20k tokens of system prompt, one request was actually cheaper on old Charon. The tasks on a personal assistant like this are easy for most models. I never expected there to be any big difference in the quality of the answers. Just like I said above, this has worked since I first made it. It’s all of the other things, excluding the quality of the answer, that can be worse. ## The main problem with this new design The upside, as I have stated, to removing rails is that the agent has more freedom in solving the task, which tends to lead to better results (on non-trivial tasks), latency and cost. But there is also a downside. I removed rails. The old agent had a `create_event` tool. It was the only way to write to my calendar. In new Charon, Claude has to ask me before it runs a `gcalcli` command that adds, changes or deletes an event. The issue here is that the new agent can, in theory, write a Python script to a scratch folder and run it without asking, and that script could call the Calendar API directly. It can do far more than that. Once you give the agent the ability to run scripts it wrote, it can bypass a lot of safeguards you might have implemented. I honestly don’t really care about this for a personal assistant. But not all projects are personal assistants. _____&#xNAN;_calendar writes ``` # old Charon ⏺ create_event(title, start, end) the only code that writes to the calendar # new Charon, .claude/settings.json "ask": ["Bash(gcalcli add *)", "Bash(gcalcli edit *)", "Bash(gcalcli delete *)", …] "allow": [ …, "Edit(//tmp/charon/**)", "Bash(python3 /tmp/charon/*)" ] # new Charon, what those settings let through ⏺ Bash(gcalcli add …) asks me first ⏺ Write(/tmp/charon/add_event.py) allowed ⏺ Bash(python3 /tmp/charon/add_event.py) allowed: Calendar API, no question asked ``` The settings lines are copied from new Charon. The last two steps never happened in a run, but nothing in the settings stops them. ## A client project Let’s think of a typical client project where the issue I just described matters much more than it does for my personal assistant. Let’s say a company wants users to be able to query multiple databases in different systems, all in plain English. There needs to be a chat front end, and different users need to see different types of data. The most common way to design this is to make an orchestrator agent that picks the domain and routes to specialist agents, one per data source, each with their own tools for each of the tasks. And perhaps, before a query gets routed to the orchestrator, an authentication layer that decides what subagents the user might have access to. This is the old Charon of B2B. This is also writing scaffolding where the model’s thinking is done for it. The existence of a tool for each task is us making the steps in advance, and the existence of every specialist (as an agent as tool) creates a bottleneck where information gets passed along. How good a job the specialist does depends on the words the orchestrator sends. Let’s remove the orchestrator. Each specialist becomes a skill. A skill that will be read when a question needs that information. The tool per task becomes a CLI with good `--help` instructions. And let’s keep a workspace per user, so the files the agent created are always there. The agent should also have access to bash, so it can read the skills and write any logs or documentation. The usual design **Chat front end** **Authentication layer**decides which specialists you get **Orchestrator agent**picks the domain a task description **Sales DB**agent, a tool per task **CRM**agent, a tool per task **Warehouse**agent, a tool per task Sales DB CRM Warehouse Without the orchestrator **Chat front end** login **Identity provider**your login maps to a database role Sandbox, one workspace per user **One agent with bash** **Skills**one per data source, read when needed **CLIs**with good `--help` **Files**logs, notes and results that stay SQL through a CLI, the only way out **Data proxy**holds the real credentialsread-only rolelogin → DB rolelogs every query Sales DB CRM Warehouse The same product, two ways. On the right, the agent can't reach anything except the proxy, and the proxy can't write. And because changing your entire architecture can be a bit challenging, at least for starting out, I recommend using the [Strands harness](https://strandsagents.com/blog/introducing-strands-harness/). ### How do you safeguard something that has this level of agency? So how do we stop the agent from editing or deleting parts of the database? You cannot give it access to the database itself. Ever. The main idea here is to make a data proxy (a small web service outside of the sandbox). So the agent can’t connect to the database. It can only send queries to a middleman. It writes SQL and sends it through a CLI. Then the proxy, which has the real credentials, forwards that to the DB. And the proxy connects with a read-only role, so an update or delete fails automatically. If the credentials were kept in the sandbox, the agent could connect directly and bypass the proxy’s identity checks and audit logs. Database-enforced read-only permissions would still apply. The sandbox can also reach the proxy and nothing else. That keeps the proxy the only way to the database, and it stops the agent from sending data anywhere else, by mistake or because something it read told it to. Even Strands, the framework old Charon is built on, now says this in the [docs for its new harness](https://strandsagents.com/docs/user-guide/harness/tools/shell-and-files/): “To isolate what the agent can touch, run it under a sandbox rather than trying to restrict the tools themselves.” Besides making sure the agent can’t change the DB, we need to make sure that we know who is querying the DB, and we need to know what the agent did. We do the first thing by checking the login from the identity provider and mapping it to a database role, which decides which tables and rows that user can see. That replaces the authentication layer that picked subagents. We do the second thing by just logging the queries themselves when they reach the proxy. ## Give it a year At the start I said you’d get laughed out of the room for building old Charon today. I wonder what this folder will look like in a year. As I write this, [skills](https://claude.com/blog/skills) are one year and four days old. A year ago they didn’t exist, and now half of new Charon’s instructions are one. AGENTS.md, skills, permission files. I wonder how much will change in a year. I wonder what models will outgrow. Will it be most of what we do today? Or almost nothing? Will we have specialized swarms? Will specialized subagents be viable again? I don’t know what changes next. I think the guardrails give out last. The proxy. The sandbox. But a year ago I wouldn’t have guessed correctly either. I’ll let new Charon have the last word. One of the four requests asked how I slept last week. This is what it said: _____&#xNAN;_charon ``` > Add Piranesi to my reading list. How did I sleep last week? ⏺ I added Piranesi to your reading list. […] Your sleep data stops on 7 August 2025, more than a year ago. The last week on record runs from 1 to 7 August. […] Nothing has been logged since, so I can't tell you how you sleep now. If you want trends that mean something, start logging again. ``` That was the last week of my internship. ## References 1. GitHub. _GitHub MCP Server._ [github.com/github/github-mcp-server](https://github.com/github/github-mcp-server) 2. OpenAI (2026). _OpenAI – Hugging Face Incident Technical Report._ On agents in a cyber evaluation escaping their sandbox and compromising parts of Hugging Face’s production infrastructure in July 2026. [cdn.openai.com](https://cdn.openai.com/pdf/67869394-cb91-4c12-888c-5cbd85c7814c/OpenAI-Hugging-Face%20Incident-Technical-Report.pdf) 3. Hugging Face (2026). _Security incident disclosure, July 2026._ 16 July 2026. [huggingface.co/blog](https://huggingface.co/blog/security-incident-july-2026) 4. OpenAI (2026). _Navier–Stokes announcement._ 8 September 2026. A Lean-checked proof that the 3D Navier–Stokes equations can blow up in finite time under a smooth external force. [openai.com](https://openai.com/index/navier-stokes-solution/) 5. Scientific American (2026). _Did OpenAI Solve the Wrong Navier-Stokes Problem?_ 21 September 2026. [scientificamerican.com](https://www.scientificamerican.com/article/did-openai-solve-the-wrong-navier-stokes-problem/) 6. ARC Prize (2024). _OpenAI o3 Breakthrough High Score on ARC-AGI-Pub._ 20 December 2024. [arcprize.org](https://arcprize.org/blog/oai-o3-pub-breakthrough) 7. ARC Prize Foundation (2025). _ARC-AGI-2._ Benchmark description and paper (arXiv:2505.11831). [arcprize.org/arc-agi/2](https://arcprize.org/arc-agi/2) 8. Anthropic (2026). _Claude Fable 5 and Claude Mythos 5._ 9 June 2026. Describes Fable 5 as a Mythos-class model made safe for general use. [anthropic.com/news](https://www.anthropic.com/news/claude-fable-5-mythos-5) 9. Anthropic (2026). _Project Glasswing._ 7 April 2026. Announces Claude Mythos Preview. [anthropic.com/glasswing](https://www.anthropic.com/glasswing) 10. ARC Prize. _ARC-AGI Leaderboard._ Semi-Private set, accessed 19 October 2026. [arcprize.org/leaderboard](https://arcprize.org/leaderboard) 11. ARC Prize (2026). _OpenAI’s GPT-6 Astra on ARC-AGI-3._ 3 September 2026. [arcprize.org](https://arcprize.org/blog/astra) 12. METR (2025). _Measuring AI Ability to Complete Long Software Tasks._ arXiv:2503.14499. [arxiv.org/abs/2503.14499](https://arxiv.org/abs/2503.14499) 13. METR. _Time horizons of frontier models (Time Horizon 1.1)._ Opus 4 1.67 h, Opus 4.5 4.88 h, Opus 4.6 11.98 h. Accessed 19 October 2026. [metr.org/time-horizons](https://metr.org/time-horizons/) 14. METR (2026). _Time horizon estimate for an early version of Claude Mythos Preview\._ Post on X, May 2026. [x.com/METR\_Evals](https://x.com/METR_Evals/status/2052896621760004602) 15. Anthropic (2026). _Claude Fable and Mythos 5.1._ 1 September 2026. [anthropic.com](https://www.anthropic.com/claude-fable-and-mythos-5-1) 16. Anthropic (2026). _Measuring agent autonomy._ 18 February 2026. [anthropic.com/research](https://www.anthropic.com/research/measuring-agent-autonomy) 17. _gcalcli: Google Calendar command line interface._ [github.com/insanum/gcalcli](https://github.com/insanum/gcalcli) 18. GitHub. _GitHub CLI._ [cli.github.com](https://cli.github.com/) 19. Open Library. _Search API._ [openlibrary.org](https://openlibrary.org/dev/docs/api/search) 20. _OMDb API: the Open Movie Database._ [omdbapi.com](https://www.omdbapi.com/) 21. _yt-dlp._ [github.com/yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp) 22. _Strands Agents._ Open-source agent SDK. [strandsagents.com](https://strandsagents.com/) 23. _OpenRouter._ [openrouter.ai](https://openrouter.ai/) 24. Anthropic. _Claude Code headless mode._ [code.claude.com/docs](https://code.claude.com/docs/en/headless) 25. Strands Agents (2026). _Introducing Strands harness: frontier performance with 28% lower token cost._ 21 September 2026. [strandsagents.com/blog](https://strandsagents.com/blog/introducing-strands-harness/) 26. Strands Agents. _Harness: shell and files._ Quoted from the section “Everything routes through the sandbox”. [strandsagents.com/docs](https://strandsagents.com/docs/user-guide/harness/tools/shell-and-files/) 27. Anthropic (2025). _Introducing Agent Skills._ 16 October 2025. [claude.com/blog/skills](https://claude.com/blog/skills)