Back to blog

Product · Jun 19, 2026

How Facio Picks the Right Tool for the Job: The Decision Framework Behind Tool Selection in AI Agents

A Facio agent has 25+ native tools plus dynamic MCP extensions. Picking the wrong tool for the task is one of the most common failure modes — agents waste iterations, produce wrong results, or trigger unnecessary HITL gates because they reached for the wrong primitive. Facio's tool selection framework turns tool choice into a decision the agent reasons about explicitly. Here's how the framework works and why tool selection is a learnable skill.

Tool SelectionDecision FrameworkAgent ReasoningTool ArchitectureBest Practices

How Facio Picks the Right Tool for the Job: The Decision Framework Behind Tool Selection in AI Agents

A Facio agent has 25+ native tools plus dynamic MCP extensions. The tool surface is large by design — composability requires coverage — but the size creates a real problem: agents can pick the wrong tool.

An agent that uses exec("cat file.txt") instead of read_file(path="file.txt") wastes iterations and burns tokens. An agent that uses read_file on a 50,000-line log file instead of grep produces output that overwhelms the context. An agent that uses web_search when it should have used recall misses the curated, private context for a question that the user already answered last week.

Picking the right tool for the task is one of the most common failure modes in agentic systems. Facio's approach is to turn tool selection into a decision the agent reasons about explicitly — with a clear framework, observable rules, and learned patterns. Here's how the framework works and why tool selection is a learnable skill.

Why Tool Selection Is Hard

Tool selection feels like a solved problem in software engineering. A developer writes code, the function names are explicit, and the compiler tells you when you got it wrong. For an AI agent, the function names are presented as options in context. The "compiler" doesn't reject wrong choices — the agent gets an error from the runtime, by which point it has already spent an iteration and possibly derailed its plan.

The difficulty compounds with the number of tools:

  • More tools = more ambiguity. When the agent has 5 tools, the choice is usually obvious. When it has 30+, the boundaries blur. read_file vs. exec("head file") vs. grep vs. web_fetch for "read this content" — multiple tools can technically produce the result.
  • Composability creates choices. A research task can use web_search + web_fetch + read_file + grep or web_search + browser_navigate + read_file. The agent has to pick the right combination.
  • Tool overlap is intentional. Facio's tools overlap on purpose — exec can do almost anything the file tools can do, web_fetch can read articles that browser_navigate can also read. The overlap gives the agent flexibility, but it also creates decision points.
  • Context shifts the right answer. A read_file call is fine for a 1KB config file and disastrous for a 100MB log file. The same tool, different contexts, different right answers.

The result: tool selection is a per-call decision the agent has to make correctly. Get it wrong, and the agent pays in iterations, in token cost, in context window bloat, or in error responses that derail its plan.

The Decision Framework

Facio's approach to tool selection is structured around four decision dimensions. The agent reasons about each one explicitly before picking a tool:

Dimension 1: What Kind of Action Is This?

The first decision is whether the task is perception (read), action (modify), or coordination (configure).

TASK: "Find the database password in the .env file"
TYPE: Perception (read-only)
→ File tools, not exec or message
TASK: "Update the database password"
TYPE: Action (modify)
→ File editing tools, possibly credential store
TASK: "Schedule a daily backup of the database"
TYPE: Coordination (configure)
→ cron or heartbeat tools

The agent identifies the action type before picking the tool. Most mistakes happen when the agent picks an action tool for a perception task (exec("cat") instead of read_file) or a coordination tool for an action task (manage_channel to update a file).

Dimension 2: What's the Data Source?

The second decision is where the data lives. Different sources have different tools.

Data sourceRight tool family
Local files in the workspaceread_file, write_file, edit_file, glob, grep
Files outside the workspaceexec (with appropriate safety)
Live web pagesweb_fetch (clean content) or browser_navigate (interactive)
Search-required webweb_search (then web_fetch)
Past conversations and memoryrecall
System logs and audit trailread_logs
Database or external APIexec with appropriate commands, or MCP server
Conversation partnermessage, ask_approval, ask_form, ask_selection

The agent identifies the source. Local files use file tools. Web pages use web tools. Memory uses recall. Logs use read_logs. The wrong source mapping produces the wrong tool choice.

Dimension 3: What's the Operation's Specific Shape?

Within each tool family, there are multiple tools for different operations. The agent picks the one that matches the specific shape.

For files:

"Read this file" → read_file(path=...)
"Find files by name" → glob(pattern=...)
"Find files by content" → grep(pattern=..., path=...)
"Replace text in a file" → edit_file(path=..., old_text=..., new_text=...)
"Replace one occurrence globally" → patch_file(path=..., old_text=..., new_text=..., replace_all=true)
"Create a new file" → write_file(path=..., content=...)
"Modify a Jupyter notebook cell" → notebook_edit(path=..., cell_index=..., edit_mode=...)
"Append to a file" → edit_file or write_file depending on existing content

For web:

"Find sources on a topic" → web_search(query=...)
"Read a known URL's content" → web_fetch(url=...)
"Interact with a website (login, click)" → browser_navigate + browser_click
"Download a file from a URL" → exec with curl/wget

For coordination:

"Run a one-time task later" → cron with `at`
"Run a recurring task" → cron with `cron_expr` or `every_seconds`
"Run a task at regular intervals as part of the agent's loop" → HEARTBEAT.md
"Add a new MCP server" → manage_mcp(action="add", ...)
"Add a new model" → switch_model(model=...)
"Configure credentials" → manage_credentials or credential store

The specific-shape decision is where most tool-selection errors happen. The agent has the right family but picks the wrong tool. edit_file for a new file (should be write_file). glob for content search (should be grep). web_search for a known URL (should be web_fetch).

Dimension 4: What Are the Constraints?

The final decision accounts for operational constraints:

  • Cost. switch_model to a cheap model for simple iterations. Avoid web_search when the answer is already in memory.
  • Latency. read_file is faster than exec("head ..."). web_fetch is faster than browser_navigate. Pick the faster tool when latency matters.
  • Output size. grep for specific patterns, read_file with offset/limit for large files, exec with output redirect for huge outputs. Don't pull 50MB into the context window.
  • Security/Approval. Destructive operations need HITL approval first. The agent doesn't pick exec("rm -rf") without thinking about whether it's appropriate.
  • Context budget. If the iteration budget is low, prefer tools that produce concise output. Avoid tools that produce verbose results when summary is enough.

The constraint dimension is where the agent's efficiency shows up. The agent that picks grep for "find all references to the auth flow" instead of read_file on every related file is using one iteration instead of twenty. The constraint-aware choice is the production-quality choice.

The Decision Tree

Putting the four dimensions together, the agent follows a decision tree:

1. What kind of action?
   ├── Perception → continue to step 2
   ├── Action → continue to step 2
   └── Coordination → continue to step 2

2. Where is the data?
   ├── Local workspace files → File tools
   ├── Live web → Web tools
   ├── Past memory → recall
   ├── Logs → read_logs
   ├── External system → exec or MCP
   └── Conversation partner → message or HITL tools

3. What's the specific operation?
   ├── File family: read_file | write_file | edit_file | glob | grep | notebook_edit
   ├── Web family: web_search | web_fetch | browser_navigate | browser_click
   ├── Coordination family: cron | heartbeat | manage_mcp | switch_model | manage_credentials
   └── Memory family: recall | read_logs

4. What are the constraints?
   ├── Cost → prefer cheap model, avoid redundant queries
   ├── Latency → prefer direct over indirect
   ├── Output size → prefer targeted over comprehensive
   ├── Security → prefer non-destructive, escalate if destructive
   └── Context budget → prefer concise over verbose

5. Pick the tool that wins on all four dimensions.

The tree is simple but explicit. The agent that reasons through the tree before picking a tool makes fewer mistakes than the agent that picks by pattern matching.

Common Tool-Selection Mistakes

Despite the framework, certain mistakes happen repeatedly. Knowing them helps the agent (and the developer) avoid them.

Mistake 1: exec("cat file.txt") Instead of read_file

# Wrong:
exec(command="cat projects/config.json")
# 10,000 character output dumped into context

# Right:
read_file(path="projects/config.json")
# Clean, structured, no shell parsing

exec is for invoking the system, not for reading files. The file tools are optimized for file access. The wrong choice burns tokens on shell overhead and produces messier output.

Mistake 2: read_file on a Huge File

# Wrong:
read_file(path="huge-server.log")
# 50MB of output overwhelms the context

# Right:
exec(command="grep ERROR huge-server.log | head -50")
# 50 lines of relevant content

read_file is for files the agent can reasonably fit in context. For larger files, the agent uses exec with grep/head/tail/awk to extract the relevant slice.

Mistake 3: web_search for a Known URL

# Wrong:
web_search(query="GitHub status page")
# Returns search results, agent fetches the actual page

# Right:
web_fetch(url="https://www.githubstatus.com/")
# Direct content extraction

web_search is for finding sources. When the source is already known (from memory, from the user, from a previous search), the agent skips search and uses web_fetch directly.

Mistake 4: web_fetch for Interactive Pages

# Wrong:
web_fetch(url="https://app.example.com/dashboard")
# Fetches login wall, no actual content

# Right:
browser_navigate(url="https://app.example.com/dashboard")
browser_type(...) for login
browser_snapshot() for content

web_fetch is for static, public content. For pages behind authentication, requiring JavaScript, or needing interaction, the agent uses the browser tools.

Mistake 5: recall for Current Information

# Wrong:
recall(query="current weather in Berlin")
# Returns memory of past weather, not current

# Right:
web_search(query="weather Berlin now")
# Or use the weather MCP server

recall is for the agent's memory and history. Current, external information comes from web_search or specialized MCP servers.

Mistake 6: message for Interactive Workflows

# Wrong:
message(content="Please approve: deploy to production?")
# Sends a text message, human can't approve in-place

# Right:
ask_approval(title="Deploy to production?", options=[...])
# Renders an interactive approval card

message is for delivering information. ask_approval, ask_form, and ask_selection are for interactive workflows where the human needs to make a decision or provide structured input.

Mistake 7: write_file for Partial Edits

# Wrong:
# Read entire file
read_file(path="config.yaml")
# Modify in memory
config["new_field"] = "value"
# Write entire file back
write_file(path="config.yaml", content=full_content)

# Right:
edit_file(path="config.yaml", old_text="existing_field: value", new_text="existing_field: value\nnew_field: value")

edit_file is for surgical changes. write_file rewrites the entire file, which can lose content (comments, formatting) the agent didn't see.

How Tool Selection Improves Over Time

The framework is a starting point. The agent's tool selection improves through three feedback mechanisms:

1. Runtime Error Patterns

When the agent picks the wrong tool, the runtime returns a structured error. The agent learns from the error and adjusts the next pick:

exec(command="cat huge.log")
# Error: output exceeded 10,000 character truncation limit

# Next session:
exec(command="head -100 huge.log")
# Clean output, no truncation

The error pattern is captured. Future sessions use the right tool from the start.

2. Inline Learning

When the user corrects the agent's tool choice, the correction is captured in MEMORY.md:

edit_file(MEMORY.md)
# Old: "## Tool Notes"
# New: "## Tool Notes
# - For large log files, use `exec` with `grep`/`head`/`tail`, not `read_file`
# - For interactive web pages, use browser_navigate + browser_click, not web_fetch"

The lesson is durable. Future sessions load the guidance as passive context and apply it automatically.

3. Reflection-Curated Heuristics

Periodically, Reflection consolidates the agent's accumulated tool-selection wisdom:

## Tool Selection Heuristics (curated 2026-06-15)
- File content search → grep, not read_file + scan
- Known URL → web_fetch directly, skip web_search
- Interactive page → browser_*, not web_fetch
- Recent conversation context → recall before web_search
- Memory file modifications → edit_file with surgical old_text/new_text, not write_file

The heuristics are distilled from many sessions into the most useful patterns. The agent loads them on every session and applies them consistently.

When the Framework Breaks Down

The framework isn't infallible. Some situations require judgment:

Ambiguous data sources. "Find the latest commit" — is it in git (exec), in a file (read_file), or in a log (read_logs)? The agent reasons about which is most likely and tries the most direct first.

Tools with overlapping capabilities. exec("head file.txt") vs. read_file(path="file.txt", limit=10) — both can read the first 10 lines. The agent picks based on the broader context (do I need other shell features? am I in a non-shell workflow?).

New situations without prior pattern. A novel task may not have a clear framework match. The agent reasons by analogy, picks the closest tool, observes the result, and learns from the outcome.

Constraints conflict. The fastest tool is the most expensive. The cheapest tool is the slowest. The agent weighs the tradeoffs and picks the best balance for the current context.

These judgment calls are where agent quality varies. The framework gives structure; the agent's reasoning fills the gaps. The Reflection process captures the successful judgments as heuristics. The agent gets better at tool selection over time.

Bottom Line

Tool selection is a per-call decision the agent has to make correctly. Get it wrong, and the agent pays in iterations, in tokens, in error responses, in context window bloat. Get it right, and the agent's work is efficient and accurate.

Facio's tool selection framework gives the agent a structured way to reason about tool choice: identify the action type, locate the data source, pick the specific operation, account for constraints. The four-dimension decision tree isn't a heuristic — it's an explicit reasoning process the agent runs before every tool call.

The framework doesn't eliminate mistakes. It makes mistakes visible, learnable, and improvable. The agent that makes a tool-selection error gets structured feedback, captures the lesson via inline learning, and consolidates the wisdom via Reflection. The next session starts with the lesson in context.

Because tool selection isn't a one-time design decision. It's an ongoing operational skill. The agent that gets better at it over time is the agent that gets more efficient, more accurate, and more valuable with every passing session.


See the tool selection documentation for the full decision tree, common mistake patterns, and the inline learning workflow for tool-selection lessons.

Keep reading

More on Product

View category
Jun 18, 2026Product

Facio's Reflection Process: How Periodic Memory Curation Keeps AI Agents Honest at Scale

Memory that grows without curation becomes noise. Facts accumulate, contradictions pile up, stale entries linger, and the agent's passive context fills with information that no longer matters. Facio's Reflection process is the periodic curator that keeps MEMORY.md honest — identifying staleness, resolving contradictions, consolidating patterns, and pruning noise. Here's how the curator works and why automated memory hygiene is a non-negotiable for production agents.

Jun 17, 2026Product

Facio's Self-Healing Agents: How Error Detection, Diagnosis, and Recovery Run as a Continuous Loop

AI agents that fail in production are a fact of life. The question isn't whether your agent will encounter an error — it's what happens after. Facio's self-healing architecture turns failures into recovery actions through a continuous detection-diagnosis-recovery loop. The agent detects, classifies, and resolves issues without human intervention for routine cases, and escalates intelligently when it can't. Here's how the loop works.

Jun 16, 2026Product

Facio's Two-Layer Memory: How Passive Context and Active Recall Give AI Agents Institutional Knowledge

AI agents with no memory are amnesiacs — they start every session knowing nothing about the user, the project, or the prior work. Facio's two-layer memory architecture combines passive context (always loaded) with active recall (query-based search) to give agents institutional knowledge that grows over time. Here's how the layers work, what each is good for, and why the combination beats either approach alone.