Back to notes
Tool callingTutorial7 min

Build a tool-calling workflow with clear function boundaries

How to design tools that let a model act inside a workflow without gaining broad, unsafe access to your product.

Open source doc

Real workflow example

An assistant needs to help a proposal team find relevant tenders. It should search, compare, and summarize records, but it should not change eligibility status or archive opportunities by itself.

Expose read-only tools such as search_qualified_tenders and get_tender_documents first. Keep destructive or workflow-changing actions behind explicit user approvals, server authorization, and ordinary UI buttons.

The model becomes useful for discovery and explanation while the product keeps ownership of final state transitions.

Implementation approach

This guide is anchored in OpenAI function calling guide. Use the official API behavior as the boundary, then design the surrounding product state so the feature can be reviewed, retried, and improved.

  1. Name tools after the business action, such as searchQualifiedTenders or createHandoffSummary.
  2. Keep the input schema small and use IDs from your system instead of letting the model invent resources.
  3. Validate tool arguments before execution and reject unknown fields.
  4. Return structured, minimal data that helps the next model step without leaking unrelated records.
  5. Log tool requests, execution result, duration, and authorization decision.

Narrow custom tool definition

const searchQualifiedTenders = {
  type: "function",
  name: "search_qualified_tenders",
  description: "Find tender records that match an approved industry, deadline, and region filter.",
  parameters: {
    type: "object",
    additionalProperties: false,
    required: ["industry", "deadlineBefore", "region"],
    properties: {
      industry: { type: "string" },
      deadlineBefore: { type: "string", description: "ISO date" },
      region: { enum: ["EU", "US", "Balkans", "Global"] },
    },
  },
};

Field notes

  • Tools should express product capabilities, not database tables.
  • Every tool needs narrow inputs, predictable outputs, and explicit authorization.
  • The model can request a tool call, but your server decides whether it is allowed.

Mistakes to avoid

  • Do not expose a generic run_sql or update_record tool.
  • Do not let the model supply tenant, role, or owner values.
  • Do not return records the current user cannot see in the product UI.

Ready checklist

  • Server-side authorization
  • Argument schema validation
  • No destructive tool without approval
  • Operational logging
  • Tool output is scoped to the workflow
Practical note
Name tools after business actions. A tool called search_qualified_tenders is easier to reason about than one called query_database.

Use this as an implementation constraint, not just advice. The interface, server code, and validation path should make the same behavior true.

Apply this to a build
Contact
Bring the product pressure, system constraints, and expected business outcome.
Send the desired outcome, users, current bottleneck, stack, and timeline. I will respond with a practical senior engineering path for the build.