Diagram showing an AI agent calling external tools and APIs

Tool Results, Observations, and Agent State

AGAI 201 · Function Calling Foundations

Learn how agents interpret tool results, preserve state across steps, and decide whether to continue, stop, retry, or escalate.

Key terms

tool result = observationstate = goal + history + evidenceclear outputs → better decisionsstopping conditions prevent runaway loops

Learning objectives

  • Explain how tool results function as observations.
  • Design useful success and error result formats.
  • Describe what agent state should track across tool calls.
  • Define stopping conditions for multi-step tool loops.

A tool call is only half of the story. The other half is what the agent does with the result. In agentic systems, tool outputs become observations: evidence about the current state of the task or environment.

An agent does not simply call a tool and stop. It interprets the result, updates its internal state, and decides what to do next. This may mean answering the user, calling another tool, retrying with different arguments, asking for clarification, or escalating to a human.

A useful mental model is:

Tool call = action
Tool result = observation
Agent state = memory of goal, context, actions, and evidence

The quality of tool results has a major impact on agent reliability. If tool results are vague, inconsistent, overly verbose, or missing status information, the model may misinterpret them.

Tool results should be designed

Many developers spend time designing input schemas but neglect output schemas. This is a mistake. A tool result should communicate not only data, but also whether the operation succeeded.

Weak tool result:

{
  "message": "Done"
}

Better tool result:

{
  "success": true,
  "operation": "get_order_status",
  "order_id": "ORD-10492",
  "status": "shipped",
  "carrier": "UPS",
  "estimated_delivery": "2026-06-07",
  "retrieved_at": "2026-06-04T14:22:00Z"
}

The better result gives the model enough information to answer accurately. It also makes logs easier for developers to inspect.

For failures, avoid ambiguous results:

{
  "success": false,
  "error_code": "ORDER_NOT_FOUND",
  "message": "No order exists with ID ORD-99999.",
  "retryable": false
}

The retryable field is especially useful. It helps the orchestration layer and model distinguish between temporary failures and permanent blockers.

Agent state across tool calls

Agent state is the information the system maintains while working on a task. This state may include:

  • The user’s original goal
  • Known constraints
  • Tools already called
  • Tool results received
  • Intermediate decisions
  • Pending actions
  • Errors encountered
  • Confirmation requirements
  • A final answer draft

For a simple one-shot tool call, state may be minimal. For a multi-step agent, state becomes essential.

Consider a coding agent asked to fix a test failure. Its state might look like this:

{
  "goal": "Fix failing login test",
  "files_read": ["tests/login.test.ts", "src/auth/login.ts"],
  "commands_run": ["npm test -- login"],
  "current_hypothesis": "Login function no longer maps emailAddress to email.",
  "last_error": "Expected 200 but received 400",
  "next_step": "Inspect request payload construction"
}

This state helps the agent avoid repeating itself and supports more coherent decision-making.

Observation quality matters

Tool results should be concise but complete. If a tool result dumps 50,000 lines of logs into the context, the model may miss the important error. If it returns only “failed,” the model cannot recover.

A good tool should summarize the most relevant information and include raw details only when needed.

For command execution, compare:

{
  "success": false,
  "stdout": "... enormous log ...",
  "stderr": "... enormous log ..."
}

with:

{
  "success": false,
  "command": "npm test -- login",
  "exit_code": 1,
  "summary": "One test failed: should log in with valid credentials.",
  "relevant_error": "Expected status 200 but received 400 at tests/login.test.ts:42",
  "truncated": true,
  "full_log_ref": "log_abc123"
}

The second result is easier for the model to use and easier for a developer to audit.

Deciding what happens next

After receiving a tool result, the agent must choose one of several next actions.

It may answer if the result satisfies the user’s request.

It may continue if the result reveals a new step. For example, a search result may point to a document that must be fetched.

It may retry if the error is temporary or the arguments were incomplete.

It may ask for clarification if the tool result shows ambiguity.

It may escalate if the action requires permission or exceeds the agent’s authority.

A simple decision policy might be:

if success and goal_satisfied:
  answer user
elif success and more_info_needed:
  call next tool
elif failure and retryable:
  retry with adjusted arguments
elif failure and missing_user_input:
  ask user for clarification
else:
  explain blocker and stop

This policy can be implemented in code, encoded in a system prompt, or handled through a framework.

Example: search then fetch then answer

A research agent might use a two-step flow:

User: What changed in version 2.1 of this library?

Step 1: search tool result:

{
  "success": true,
  "results": [
    {
      "title": "Library Release Notes",
      "url": "https://example.com/releases",
      "snippet": "Version 2.1 introduces streaming support and improved error handling."
    }
  ]
}

The agent should not stop at the snippet if the user needs accuracy. It should fetch the release notes.

Step 2: fetch tool result:

{
  "success": true,
  "url": "https://example.com/releases",
  "content_summary": "Version 2.1 added streaming responses, changed timeout defaults, and deprecated the legacy client.",
  "published_date": "2025-03-18"
}

Now the agent can answer with confidence.

State and stopping conditions

Agents need stopping conditions. Without them, a tool loop may continue too long, retry unnecessarily, or chase irrelevant information.

Common stopping conditions include:

  • The user’s requested information has been found.
  • A requested action has been completed.
  • A tool error is non-retryable.
  • The agent has reached a maximum number of tool calls.
  • Required permission is missing.
  • The task is ambiguous and cannot proceed safely.

For example:

{
  "max_tool_calls": 8,
  "require_confirmation_for": ["send_email", "delete_file", "update_database"],
  "stop_on_non_retryable_error": true
}

These limits should not be afterthoughts. They are part of the agent design.

Practical takeaway

Tool use is not just about calling functions. It is about managing observations and state. A good agent knows what it has tried, what it learned, what remains uncertain, and when to stop.

Design tool results as carefully as tool inputs. Include success flags, error codes, relevant summaries, timestamps, and retry guidance. Then give the agent or orchestration layer a clear policy for continuing, retrying, asking, escalating, or answering.

Sign in to track your progress.

Up next · Module 2

Designing and Building Tool-Using Agents

Move from basic function calls to practical tool-using agents. This module teaches schema design, tool selection, orchestration patterns, and implementation strategies using standard application architecture.

Ask your AI guide

AI Chat· Tool Use & Function Calling — Tool Results, Observations, and Agent State
🤖

Ask anything about Tool Use & Function Calling — Tool Results, Observations, and Agent State, or choose a suggested question below.

AI responses are educational and may not be perfectly accurate. Press Enter to send, Shift+Enter for new line.