SwiftRelay

← All sprint notes

First Lap: Function Calling with Chat Completions

Protocol pit stopEN

Function calling lets a chat model request an action from your application instead of guessing an answer. The model selects a tool and supplies structured arguments; your code validates the request, executes the function, and returns the result. This first lap builds a read-only order lookup using Chat Completions.

1. Connect your Chat Completions client

Install the OpenAI Python SDK and keep your API key in an environment variable, not in source control. SwiftRelay is a practical option for using an OpenAI-compatible SDK through one endpoint, with per-token billing. Sign up for SwiftRelay to get a small gift credit for your first requests.

Initialize the client with your SwiftRelay key and base_url="https://api.fastapirelay.com/v1". OpenAI SDKs need the /v1 suffix. Choose a model available to your account, and confirm that its Chat Completions route supports tools; OpenAI-compatible transport does not guarantee identical tool support across every model.

2. Define one narrow order lookup tool

Start with a function named get_order_status. It accepts one order identifier and returns information your application can actually retrieve. Describe its purpose clearly so the model knows when to request it.

The tools array contains this definition: {"type":"function","function":{"name":"get_order_status","description":"Look up the current shipping status of an order by its order identifier.","parameters":{"type":"object","properties":{"order_id":{"type":"string","description":"The order identifier, such as ORD-1042."}},"required":["order_id"],"additionalProperties":false}}}

This schema describes inputs, not executable code. Your application still needs a real function, or a temporary fixture, behind that name. Do not put credentials or internal database details in the description.

3. Send the question with the tool definition

Create a messages list containing a system instruction and the user's question. For example, tell the assistant: “Use the order tool for shipping questions. Never invent an order status. Ask for the order identifier if it is missing.” Then add: “What is the status of order ORD-1042?”

Call client.chat.completions.create with your selected model, messages, tools, and tool_choice="auto". Automatic selection allows the model to request the lookup when useful. It may instead answer directly or ask a clarifying question, so your application must handle responses without tool calls.

4. Inspect the assistant's tool request

Read response.choices[0].message and inspect its tool_calls field. A request might contain id="call_order_1", function.name="get_order_status", and function.arguments='{"order_id":"ORD-1042"}'. The arguments field is a JSON-encoded string, so parse it before accessing order_id.

Append the assistant message to the conversation, preserving its tool calls. With the Python SDK, message.model_dump(exclude_none=True) provides a serializable representation. Do not replace that message with a plain-text description: the next request needs the original call identifiers.

5. Validate arguments and execute your function

Dispatch only recognized function names. Validate that the parsed arguments contain a correctly formatted order identifier, then check that the authenticated customer can access that order. A model-generated identifier is not proof of authorization.

For this first run, your local function can return a fixed fixture: {"order_id":"ORD-1042","status":"shipped","estimated_delivery":"2026-08-19"}. Later, replace the fixture with an authenticated backend lookup. The model does not execute your function; your application controls whether any operation happens.

6. Return the result using the matching call identifier

Append a tool message containing the result: {"role":"tool","tool_call_id":"call_order_1","content":"{\"order_id\":\"ORD-1042\",\"status\":\"shipped\",\"estimated_delivery\":\"2026-08-19\"}"}. The content is a string containing serialized JSON, and tool_call_id must match the assistant's request.

Send the updated conversation back through Chat Completions. Keep processing tool calls until the assistant returns a final answer, subject to an application-defined iteration limit. If a turn contains multiple calls, return a corresponding result for each one before continuing.

7. Check failure paths before adding more tools

  • Missing information: Ask about an order without an identifier and confirm that the assistant requests clarification.
  • Invalid requests: Reject malformed arguments and unknown function names without executing anything.
  • Backend failures: Return a structured error without exposing secrets or stack traces.
  • Grounded answers: Confirm that the final response uses the returned status rather than inventing shipping details.

Once this loop works, add tools gradually. Keep authorization and execution in application code, and require explicit confirmation before introducing actions that change customer data.

Keep reading

Back for another lap?Log in