Logo

AWS · Agentic AI

Tools are the agent's hands: designing action groups and tool use on Bedrock

A model that can only reason is a consultant. An agent that can act is a worker. The bridge between the two is tools, and on Amazon Bedrock that bridge is the action group. Get the tools right and a modest model does real work; get them wrong and the best model in the world produces confident nonsense.

Infostatus · AWS Advanced Tier Services Partner · ~9 min read

Ask a language model to refund a customer and, on its own, it cannot. It can describe how a refund works, draft a polite email about one, even write the SQL it imagines you'd run. What it cannot do is touch your payments system. Reasoning is not action. The thing that turns a model from an articulate advisor into something that actually moves work through your business is the same thing that distinguishes a brain from a person: hands. In agent terms, hands are tools.

Without tools, an agent only talks

A tool is a capability you grant the model: a way to query a system, call an API, or take an action in the real world. Look up an order. Check inventory. Create a ticket. Issue the refund. Each tool is a defined operation the model can choose to invoke, with the result fed back into its reasoning so it can decide what to do next.

This is the whole difference between advice and work. Without tools, an agent that is asked “has order 4471 shipped?” can only speculate. With a get_order_status tool, it queries your fulfilment system, reads the real answer, and tells the customer the truth. The model still does the reasoning, deciding which tool, when, and with what arguments, but the tool is what lets the reasoning land on something true and act on it.

Action groups on Bedrock Agents

On Amazon Bedrock, you give an agent its hands through an action group. An action group is a named set of tools the agent is allowed to use, defined as an API. You describe that API either as an OpenAPI schema or as a simpler function schema (a list of functions with typed parameters), and you point it at the code that runs when a tool is called, typically an AWS Lambda function.

At runtime the flow is straightforward. The agent receives a request, reasons about it, and decides a tool is needed. Bedrock invokes your Lambda with the tool name and the arguments the model chose. Your Lambda does the work and returns a structured result. Bedrock feeds that result back into the model, which continues until it can answer. You supply the schema and the Lambda; the model supplies the judgement about which tool to call and what to pass it.

The schema is a contract, not documentation. It tells the model what each tool is called, what it does, and exactly what arguments it takes. The model never sees your Lambda code, only the schema. Everything it knows about a tool, it learns from how you describe it.

The description is the interface

This is the single most important idea in tool design, and the one most teams underweight. The agent chooses tools by reading their names and descriptions. Not by inspecting your code, not by testing behaviour, by reading natural-language text you wrote. The description is the interface the model programs against.

So a vague description is a bug. A tool named process described as “handles order operations” gives the model nothing to reason with: when two tools both sound plausible, it guesses, and a guess is a wrong call. Compare:

Vague (causes wrong calls)Clear (reliable selection)
get_data: “gets data”get_order_status: “returns shipping status and tracking for one order by ID”
update: “updates a record”cancel_order: “cancels an unshipped order; fails if already shipped”

Write descriptions for the model the way you'd write them for a competent new hire who can't ask follow-up questions. State what the tool does, when to use it, when not to, and what each parameter means. This text earns more reliability per hour of effort than almost anything else you can tune.

Design tools narrow and single-purpose

Reliable tool selection follows from reliable tools. The pattern that works is the opposite of a general-purpose “do everything” endpoint:

  • One job per tool. get_order_status, cancel_order, and issue_refund as three tools, not one manage_order with a mode argument. Distinct tools give the model distinct choices.
  • Explicit, typed parameters. An order_id of type string with a description beats a loose params object. Constrain with enums and formats where you can; the schema is also your first line of input validation.
  • Predictable behaviour. The same inputs should produce the same shape of output every time. Surprises in tool behaviour become reasoning errors in the agent.

Narrow tools are easier for the model to choose between, easier for you to test, and easier to scope for security. Breadth in a single tool is a liability, not a convenience.

Idempotency and error handling

Agents retry. A network blip, a timeout, a model that re-reasons and calls the same tool again: any of these can fire an action twice. If issue_refund is called twice, the customer should not be refunded twice. Make consequential actions idempotent, usually with a client-supplied key so a repeat call returns the original result instead of performing the action again.

Equally, when something goes wrong, tell the agent clearly. A tool that throws an opaque stack trace, or worse returns an empty success, leaves the model to hallucinate what happened. Return structured, readable errors the agent can act on:

# Lambda handler for an action group: returns a structured tool result
def handler(event, context):
    func   = event["function"]
    params = {p["name"]: p["value"] for p in event["parameters"]}

    if func == "issue_refund":
        order = lookup_order(params["order_id"])
        if order is None:
            # clear error the model can recover from, not a crash
            body = {"status": "error",
                    "reason": "order_not_found",
                    "message": "No order matches that ID. Ask the customer to confirm it."}
        elif order.refunded:
            # idempotent: the action already happened, so report it as done
            body = {"status": "ok", "refund_id": order.refund_id, "already_processed": True}
        else:
            refund = do_refund(order, key=params["idempotency_key"])
            body = {"status": "ok", "refund_id": refund.id, "amount": refund.amount}

    return {"response": {"functionResponse":
            {"responseBody": {"TEXT": {"body": json.dumps(body)}}}}}

Structured results, named error reasons, and an idempotency check let the agent recover and reason instead of looping or inventing an outcome. The exact response envelope follows the current Bedrock Agents return format; check the AWS documentation for your runtime.

Least privilege per tool

Here is a security property that catches people out: an agent inherits the union of its tools' permissions. If one tool's Lambda can read the whole customer database and another can move money, the agent effectively can do both, and so can any prompt that talks it into the wrong call.

So scope each tool's execution role to exactly what that tool needs and nothing more. The Lambda behind get_order_status gets read access to the orders table, full stop. The Lambda behind issue_refund gets permission to call the refund API, and not to read unrelated data. Separate functions with separate IAM roles give you separate blast radii. One fat Lambda with one broad role hands the whole estate to whatever the model decides to do next.

Guardrails on consequential tools

Not every tool is equal. Reading an order status is cheap to get wrong; issuing a refund, deleting a record, or sending an email to a customer is not. For consequential tools, defence in depth applies:

  • Validate inputs hard inside the tool. Treat the model's arguments as untrusted, because in effect they are. Check ranges, ownership, and state before acting.
  • Require confirmation or human approval before destructive or high-stakes actions. Bedrock Agents support a confirmation step before an action group runs; for the highest-stakes operations, route the action to a human queue rather than executing inline.

This is where tool design meets governance. The same discipline that makes an individual tool safe, least privilege, validation, an approval gate, is the operating model that lets you trust an agent with real responsibility at all.

Why good tools beat a bigger model

The instinct when an agent misbehaves is to reach for a more capable model. Usually that is the wrong lever. In our experience building agents, most failures are not reasoning failures, they are tool and integration failures: a description ambiguous enough that the model picks the wrong tool, a parameter the schema didn't constrain, an error returned as a blank instead of a reason, an action that wasn't safe to retry. A bigger model reasons more eloquently over the same broken hands and fails just as surely.

Invest accordingly. Spend your effort on naming and describing tools precisely, keeping them narrow and typed, making them idempotent, returning structured errors, and scoping their permissions tightly. That is where agent reliability is actually won. The model thinks; the tools determine whether the thinking turns into correct, safe work. On Bedrock, that work is the action group, so treat it as the product, not the plumbing.

This is one piece of a larger method

Agentic AI is a stack and an operating model, not a single product. The full guide maps the AWS agentic stack, where agents earn their keep first, governance, the economics of a digital workforce, and a sensible first 90 days.

Read: Agentic AI on AWS, building the agentic native enterprise
Infostatus is an AWS Advanced Tier Services Partner. This article is general technical guidance; validate conversions and settings against current AWS documentation and your own workload before relying on them in production.
Share this post:

Related Articles

View All Insights
25Eight: Scaling Personalised Learning with Generative AI on AWS
Case Study

25Eight: Scaling Personalised Learning with Generative AI on AWS

How AWS Cloud Managed Services Free Internal Teams to Focus on Innovation
Blog

How AWS Cloud Managed Services Free Internal Teams to Focus on Innovation

Optimising Cloud Costs: Infostatus's Approach to Cost Management, Governance, and Efficiency
Blog

Optimising Cloud Costs: Infostatus's Approach to Cost Management, Governance, and Efficiency

Join our newsletter to stay up to date

By submitting, you agree to our Privacy Policy