DEV Community

Anindya Obi
Anindya Obi

Posted on

Tool Boundaries for Agents: When to Call Tools + How to Design Tool I/O (So Your System Stops Guessing)

Tool calling is where “demo agents” go to die.

If you don’t define tool boundaries, your agent will do one of two things in production:

  • call tools for everything (slow + expensive + noisy), or
  • call tools for nothing (confident hallucinations)

This post gives you a drop-in standard you can paste into your system/router prompt so your agents stop guessing and start behaving like software.

Last week, my “helpful” agent did the most dangerous thing an agent can do: it almost did the right thing.

A user asked: “Why did my order fail to deliver?”
The agent didn’t have order data… so it guessed: “weather delays.”
Then it wrote a confident apology and moved on.

  • No tool call.
  • No verification.
  • Just vibes.

I changed one thing: I made tool usage a contract.

Next run, the agent said: “I can check your order status. What’s your order ID?”

It asked for the missing prerequisite, called the tool only when ready, and handled failures cleanly.

That’s the difference between an assistant and a production system.

Why this fails in production

Tool behavior breaks for two predictable reasons:

  • Over-calling tools: every question triggers a tool → latency + cost + messy traces
  • Under-calling tools: the agent answers without required data → hallucinations with confidence

In production, you need tool usage that is:

  • testable (you can write evals for it)
  • auditable (you can trace and debug it)
  • repeatable (it behaves the same across runs)

That only happens when you treat tool usage like an API contract, not a suggestion.

Definitions: what “tool boundaries” actually mean

Tool boundaries are the rules that decide:

  1. Trigger: when a tool MUST be called vs MUST NOT be called
  2. Prerequisites: required inputs before calling (order_id, query, file_id, etc.)
  3. I/O Contract: strict JSON for tool inputs + strict JSON outputs
  4. Failure Policy: retry vs ask user vs fallback vs escalate
  5. Auditability: what you log (trace_id, tool_name, latency, status, cost)

If you define these, your agent stops inventing workflows mid-flight.

Drop-in standard (copy/paste): Tool Boundary Contract

Paste this into your system prompt or router agent instructions.

TOOL BOUNDARY STANDARD (binding rules)

You may call tools only when the user's goal cannot be satisfied safely with internal reasoning alone.

1) MUST_CALL conditions:
- The answer requires private/user-specific data (account, orders, tickets, files, database records).
- The answer requires up-to-date or externally verifiable facts (news, prices, weather, availability).
- The answer requires computation or transformation best done by a tool (calc, parsing, file ops).
- The agent has insufficient inputs and the tool is the only way to obtain them.

2) MUST_NOT_CALL conditions:
- The user is asking for explanation, brainstorming, writing, or strategy that does not depend on external data.
- Tool prerequisites are missing (e.g., no order_id, no query, no file_id).
- A tool result would not materially change the answer.

3) BEFORE_CALL checklist:
- Identify required tool inputs.
- If missing: ask ONE targeted question to obtain them.
- Choose exactly ONE tool. Do not chain tools unless explicitly needed.

4) TOOL_IO:
- Tool inputs MUST match the declared JSON schema.
- Tool outputs MUST be treated as source of truth.
- Never fabricate tool outputs.

5) ON_ERROR policy:
- If retryable (timeout/429): retry up to 2 times with backoff.
- If not retryable (4xx validation): ask for corrected input.
- If tool unavailable: provide a safe fallback + explicit limitation + next step.

Enter fullscreen mode Exit fullscreen mode

Router decision schema (strict JSON)

This is the smallest schema that makes tool calling eval-friendly.

{
  "decision": "CALL_TOOL | ASK_USER | ANSWER_DIRECT | REFUSE",
  "reason": "string",
  "tool_name": "string | null",
  "tool_input": "object | null",
  "missing_inputs": ["string"],
  "success_criteria": ["string"],
  "fallback_plan": ["string"]
}

Enter fullscreen mode Exit fullscreen mode

If you do nothing else: enforce this.
It prevents “tool vibes” because the agent must commit to a decision.

Tool I/O template (per tool)

Every tool should publish requirements like this (even if you generate it automatically).

{
  "tool_name": "string",
  "required_inputs": ["string"],
  "optional_inputs": ["string"],
  "input_example": {},
  "output_schema": {},
  "error_shapes": [
    { "type": "timeout", "retryable": true },
    { "type": "validation_error", "retryable": false }
  ]
}
Enter fullscreen mode Exit fullscreen mode

This prevents the classic failure: “tool called with half an input” -> garbage output -> downstream chaos.

Example 1: RAG or answer directly?

User: “Explain the difference between embeddings and rerankers.”

✅ Good (ANSWER_DIRECT)

  • No external/user-specific data required
  • Provide explanation + practical usage patterns
  • No tool call

❌ Bad (CALL_TOOL)

  • “Let me search…” (wasteful)
  • More latency, no material gain
  • Boundary hit: MUST_NOT_CALL for conceptual explanations.

Example 2: User-specific data → tool is mandatory

User: “Why wasn’t my order delivered?”

✅ Good (ASK_USER → CALL_TOOL)

  • Ask for order_id
  • Call get_order_status(order_id)
  • Explain based on tool result
  • If tool fails: retry / ask / escalate

❌ Bad (ANSWER_DIRECT)

  • “Probably weather delays”
  • High hallucination risk
  • Boundary hit: MUST_CALL when the answer depends on private/user-specific data.

Example 3: Missing prerequisites (don’t guess)

User: “Check the logs and tell me why the tool failed.”

✅ Good (ASK_USER)

  • “Paste the log excerpt or share the trace_id.”
  • Then route to the right tool/analysis path.

❌ Bad (CALL_TOOL)

  • Calls a “log tool” with empty input
  • Or invents a plausible stack trace
  • Boundary hit: MUST_NOT_CALL when prerequisites are missing.

Example 4: Tool errors must have a policy (not improvisation)

Tool returns:

{ "status": "error", "error_type": "timeout", "message": "upstream timed out" }


Enter fullscreen mode Exit fullscreen mode

✅ Good

  • Retry up to 2 times
  • If still failing: explain limitation + next step
  • Offer a user-facing fallback (manual check, later retry, alternative source)

❌ Bad

  • Pretend it worked
  • “Your order is delivered” (catastrophic)

Boundary hit: never fabricate tool outputs + enforce ON_ERROR.

What can be automated safely (without losing correctness)

Once boundaries are explicit, automation becomes safe:

  • Tool registry generation from code (required inputs, output schema, error shapes)
  • Tool-call linting (block calls when required inputs are missing)
  • Boundary-based routing (router agent emits strict JSON)
  • Structured traces (trace_id, tool_name, latency, status, cost)
  • Eval harness for MUST_CALL vs MUST_NOT_CALL decisions
  • Fallback templates for timeout / 429 / validation errors

This is where teams stop “debugging prompts” and start debugging systems.

HuTouch + Work2.0 (the new way of building)

I’m building HuTouch to automate the boring parts of prompt design for AI engineers routers, scopes, schemas, eval sets so your agents ship with guardrails by default.

Here's how: Instructions & Prompt Design

And this ties into what I call Work2.0:

  • We stop confusing effort with value.
  • We automate the repeatable steps that don’t need deep skills.
  • We take time back for the work (and life) that actually matters.

If you want early access to HuTouch’s prompt automation workflow, here’s the form: Early Access Form Link

Quick checklist (print this)

  • Do we have explicit MUST_CALL and MUST_NOT_CALL rules?
  • Does every tool declare required_inputs and output_schema?
  • Does the router return strict JSON (CALL_TOOL / ASK_USER / ANSWER_DIRECT / REFUSE)?
  • Do we block tool calls when prerequisites are missing?
  • Do we have an error policy (retry / ask user / fallback / escalate)?
  • Are tool calls auditable (trace_id, latency, status, cost)?
  • Do we test boundaries with eval prompts that try to force bad behavior?

Top comments (0)