🤖 AI Tools

Amazon Bedrock Converse API Tool Use Planner: toolConfig and toolSpec JSON Schemas, toolChoice Options, the tool_use Stop Reason Loop, toolResult Error Status, Inference Profiles, and boto3 Code

Plan a tool calling agent on Amazon Bedrock with the Converse API: write toolSpec definitions with inputSchema JSON, choose auto, any, or a forced tool, run the stopReason tool_use loop that returns toolResult blocks, mark tool errors with status, pick an inference profile ID, and get working boto3 code plus a test checklist.

0.0
0Reviews
P
October 9, 2026

Prompt

Act as an AWS generative AI engineer who builds tool using assistants on Amazon Bedrock with the model agnostic Converse API in boto3 (bedrock-runtime client, converse and converse_stream).

Inputs:
- Model and how it is reached: model ID or inference profile ID copied from the Bedrock console, plus region and whether model access is enabled: [ModelId]
- Tools the assistant needs: name, what it does, its parameters with types and allowed values, and the backend call behind it: [ToolList]
- Conversation flow: what the user asks, which tool should run when, and when the model must answer without a tool: [ConversationFlow]
- Error policy: what happens on timeouts, not found, permission denied, and bad arguments: [ErrorPolicy]
- Runtime limits: max tool rounds per request, latency budget, streaming or not, logging rules for PII: [RuntimeLimits]
- Output format: [Format]

Generate:
1. A toolConfig block: one toolSpec per tool in ToolList with a name, a description written for the model (when to use it and when not to), and inputSchema.json with types, enums, required fields, and additionalProperties false.
2. A toolChoice decision: auto for normal turns, any when a tool call is required, or tool with a name to force one tool, and a note to check that the chosen model supports that option.
3. A system prompt block (system list of text) that states the ConversationFlow rules and tells the model never to invent tool results.
4. The request loop in Python: call converse with modelId, messages, system, inferenceConfig (maxTokens, temperature), and toolConfig; when stopReason is tool_use, append the assistant message, run each toolUse block, and send one user message with matching toolResult blocks by toolUseId; stop at end_turn or the round cap from RuntimeLimits.
5. Error handling from ErrorPolicy: return a toolResult with status error and a short text the model can explain to the user, and retry throttling exceptions with backoff.
6. Argument validation before running any backend call, rejecting values outside the schema.
7. A test checklist: one prompt per path in ConversationFlow, a forced error case, a no tool question, and the usage fields (inputTokens, outputTokens) to log per round.

Constraints:
- Read the model ID from configuration; never hardcode or guess an ID.
- Never execute a tool the model names unless it is in ToolList.
- Keep secrets and PII out of logs per RuntimeLimits. No em dashes.

Instructions

Replace every [bracket] with your details before running. Works on ChatGPT, Claude, and Gemini.

Generated Output

This image was generated using the prompt above.

Amazon Bedrock Converse API Tool Use Planner: toolConfig and toolSpec JSON Schemas, toolChoice Options, the tool_use Stop Reason Loop, toolResult Error Status, Inference Profiles, and boto3 Code - Result

Examples

Example Input

ModelId: Claude Sonnet cross region inference profile ID from our console (us. prefix), us-east-1, model access granted; read from env BEDROCK_MODEL_ID
ToolList: lookup_ticket(ticket_id: string like "IT-12345") returns status, assignee, last update from ServiceNow; reset_mfa(employee_email: string, method: enum "authenticator" | "sms") opens an MFA reset request, never resets directly
ConversationFlow: employee asks about a ticket, call lookup_ticket; employee locked out of MFA, confirm their work email then call reset_mfa; policy questions answered from the system prompt without tools
ErrorPolicy: ticket not found returns a friendly not found; ServiceNow timeout after 8 seconds, tell the user to try again; reset_mfa for an email outside @northwind.example is refused
RuntimeLimits: max 3 tool rounds, non streaming, never log employee emails in full
Format: toolConfig, toolChoice, system, loop code, errors, validation, tests

Example Output

TOOLCONFIG
tool_config = {"tools": [
 {"toolSpec": {"name": "lookup_ticket",
  "description": "Get status of an existing IT ticket. Use only when the user gives or asks about a ticket ID.",
  "inputSchema": {"json": {"type": "object", "properties": {
    "ticket_id": {"type": "string", "pattern": "^IT-[0-9]{5}$"}},
    "required": ["ticket_id"], "additionalProperties": False}}}},
 {"toolSpec": {"name": "reset_mfa",
  "description": "Open an MFA reset request after the user confirms their work email. Does not reset MFA directly.",
  "inputSchema": {"json": {"type": "object", "properties": {
    "employee_email": {"type": "string"},
    "method": {"type": "string", "enum": ["authenticator", "sms"]}},
    "required": ["employee_email", "method"], "additionalProperties": False}}}}],
 "toolChoice": {"auto": {}}}

TOOLCHOICE
auto. Policy questions need no tool, so any or a forced tool would be wrong here. Confirm the model supports toolChoice before using any.

SYSTEM
system = [{"text": "You are the Northwind IT helpdesk assistant. Use lookup_ticket for ticket questions. Before reset_mfa, ask the user to confirm their work email. Never invent ticket details or tool results."}]

LOOP
def run(messages):
    for _ in range(3):
        r = client.converse(modelId=os.environ["BEDROCK_MODEL_ID"], messages=messages,
                            system=system, toolConfig=tool_config,
                            inferenceConfig={"maxTokens": 800, "temperature": 0.2})
        msg = r["output"]["message"]
        messages.append(msg)
        log_usage(r["usage"])
        if r["stopReason"] != "tool_use":
            return msg
        results = []
        for block in msg["content"]:
            if "toolUse" in block:
                tu = block["toolUse"]
                results.append({"toolResult": run_tool(tu["toolUseId"], tu["name"], tu["input"])})
        messages.append({"role": "user", "content": results})
    return {"role": "assistant", "content": [{"text": "Sorry, I could not finish that. Please open a ticket."}]}

ERRORS
def run_tool(tid, name, args):
    if name not in TOOLS:
        return {"toolUseId": tid, "status": "error", "content": [{"text": "Unknown tool."}]}
    try:
        return {"toolUseId": tid, "content": [{"json": TOOLS[name](**validate(name, args))}]}
    except NotFound:
        return {"toolUseId": tid, "status": "error", "content": [{"text": "Ticket not found."}]}
    except Timeout:
        return {"toolUseId": tid, "status": "error", "content": [{"text": "ServiceNow timed out after 8s; ask the user to try again."}]}
Wrap converse in a retry with backoff on ThrottlingException.

VALIDATION
- ticket_id must match ^IT-[0-9]{5}$
- employee_email must end with @northwind.example, else refuse
- method must be authenticator or sms

TESTS
1. "What's happening with IT-48213?" calls lookup_ticket
2. "I'm locked out of MFA" asks to confirm email, then calls reset_mfa
3. "How long is the password policy?" gets no tool call
4. Email at another domain is refused
5. Forced timeout returns a status error result and a polite retry message
Log inputTokens and outputTokens per round, and emails masked as j***@northwind.example.

Reviews (0)

Please login to leave a review.
Loading reviews...
Amazon Bedrock Converse API Tool Use Planner: toolConfig and toolSpec JSON Schemas, toolChoice Options, the tool_use Stop Reason Loop, toolResult Error Status, Inference Profiles, and boto3 Code - PromptDig