3 Topics
Chapter•75 Minutes

6. Tool Calling and Reliable Workflow Execution

Let models request tools while your application validates arguments, enforces permissions, handles retries, and records side effects.

How Tool Calling Works

In tool calling, the model proposes a structured call to a named function; your application validates the arguments and decides whether to execute it. The model does not automatically run your JavaScript function unless your code implements the execution loop. Tool results are returned to the model, which may then answer or request another tool.

A safe loop has bounded steps, allowed-tool lists, schema validation, authorization, timeouts, idempotency, and clear handling of malformed or repeated calls. Never expose a general-purpose shell, arbitrary SQL, or unrestricted HTTP fetch tool to an untrusted agent without strong isolation and policy controls.

Diagram
Tool execution pattern
const toolRegistry = {
  getOrderStatus: async ({ orderId }, context) => {
    const order = await orders.findVisibleToUser({
      orderId,
      userId: context.userId
    });
    if (!order) return { found: false };
    return { found: true, status: order.status };
  }
};
💡 The registry contains application-owned functions. The function checks ownership in the data query rather than trusting the model or a user-supplied order ID.
Key Takeaways
  • Tool calls are requests, not permission grants.
  • Validate arguments and user access at execution time.
  • Limit the number of tool-loop steps and apply timeouts.
Knowledge Check

Who should execute and authorize a tool call proposed by the model?

Tool Schemas, Validation, and Idempotency

Use narrow tool schemas with enums, length limits, required fields, and explicit descriptions. Validate again in application code, including business constraints that schemas cannot express. For side-effecting operations, add idempotency keys or a deduplication record so retries do not create duplicate payments, tickets, or emails.

Separate read tools from write tools. A write tool should have explicit authorization and often require user confirmation. Record who requested the action, what arguments were accepted, what policy was applied, and the result. Avoid storing unnecessary sensitive arguments in audit logs.

Validate and deduplicate a side effect
async function createSupportTicket(input, context) {
  const parsed = TicketInput.safeParse(input);
  if (!parsed.success) throw new Error("Invalid ticket arguments");

  return db.withIdempotencyKey(
    context.idempotencyKey,
    () => tickets.create({
      userId: context.userId,
      subject: parsed.data.subject,
      body: parsed.data.body
    })
  );
}
💡 TicketInput and withIdempotencyKey represent application-owned validation and deduplication helpers. Implement them using a trusted schema validator and a durable unique key in the database.
Key Takeaways
  • Use narrow schemas and validate again in the executor.
  • Make side effects idempotent where possible.
  • Audit sensitive actions and require confirmation where appropriate.
Knowledge Check

Why use an idempotency key for a side-effecting tool?

Human Approval and Multi-Step Workflows

For consequential actions, let the model prepare a proposal and ask a human to approve it before execution. The approval should bind to the exact action payload, target, and relevant version; otherwise an attacker or race could change the payload after approval. Re-check permissions and state at execution time.

A workflow state machine is often more reliable than an unconstrained agent: drafted → awaiting_approval → approved → executing → completed with explicit failure and cancellation states. Store state durably so a process restart does not lose the workflow. Define who can approve, how approvals expire, and how rejected requests are handled.

Approval state model
drafted
  -> awaiting_approval
      -> rejected
      -> approved
          -> executing
              -> completed
              -> failed / retryable
💡 Each transition should be validated by server-side policy. Approval should refer to a specific payload hash or immutable action record, and the executor should revalidate the target before acting.
Key Takeaways
  • Use state machines for durable multi-step workflows.
  • Approval must bind to the exact action.
  • Re-check permissions and current state before execution.
Knowledge Check

What should an approval bind to for a high-impact action?