Module 1 · Lesson 5
Reasoning, Tools, Actions and Observations in AI Agents
Agent behavior becomes easier to design when you separate four concepts: the model's decision process, the tools it can request, the actions your application executes and the observations returned back into context.
Reasoning is not execution
The model decides what it wants to do next. Your application decides what it is actually allowed to do. This separation is essential. A model can propose a database lookup or a refund, but deterministic code should validate the request before any side effect happens.
Tools are capability contracts
A tool exposes a capability to the model using a name, description and schema. Good tool design is not the same as writing an internal helper function. The caller is probabilistic, so the tool must communicate intent and boundaries clearly.
Anthropic's current tool-design guidance recommends choosing only useful tools, namespacing clearly, returning meaningful context, keeping responses token-efficient and carefully engineering tool descriptions and specifications.
Bad tool surface
run_query(sql: str)
execute_action(action: str, payload: dict)These tools are broad and difficult to secure. They also force the model to reason about low-level implementation details.
Better tool surface
get_order_status(order_id: str)
list_customer_invoices(customer_id: str, status: str)
request_refund(order_id: str, reason: str)The second set expresses business capabilities directly and gives authorization code a cleaner boundary.
Actions are what your software executes
A model's tool call is a request. The action is the real code path that runs after validation. That distinction lets you add permission checks, rate limits, idempotency keys, auditing, retries and human approvals without depending on the model.
Observations close the loop
After an action runs, the tool returns an observation. The model uses that observation to decide whether to continue.
User: Find overdue invoices for Acme.
Agent: call find_customer("Acme")
Observation: {"customer_id": 42}
Agent: call list_invoices(42, "overdue")
Observation: [{...}, {...}]
Agent: summarize resultsDesign observations for decision-making
Tool output should contain what the model needs for the next decision and avoid irrelevant payload. If an upstream API returns 200 fields but the agent needs five, normalize the response before adding it to model context.
| Tool output problem | Better approach |
|---|---|
| Huge raw JSON payload | Return a normalized subset |
| Ambiguous error string | Return structured error type and message |
| Internal IDs with no meaning | Add human-readable labels where useful |
| Secrets or credentials | Never return them to model context |
| Unbounded list | Paginate or cap results |
The model should not be your authorization layer
Prompts such as “never refund more than $500” are not a replacement for code that enforces a $500 limit. The tool implementation should check the authenticated user, account ownership, policy and transaction constraints.
Reasoning quality depends on tool quality
When tool names overlap, descriptions are vague or outputs are noisy, the model must spend more effort inferring how your system works. Clearer tools reduce ambiguity and often reduce the number of steps required to finish a task.
How many tools should an agent have?
There is no universal number. The right question is whether the model can reliably distinguish them. If a single agent has hundreds of overlapping operations, consider grouping capabilities, deferred tool discovery, specialized agents or MCP-based tool surfaces with filtering.
A practical tool checklist
- Give the tool one clear responsibility.
- Use descriptive names and parameters.
- Validate every argument in code.
- Keep destructive tools narrow.
- Return concise structured results.
- Classify errors so retry behavior is explicit.
- Add authorization independently of prompts.
- Log side effects and important tool calls.