OpenAI agents leverage the platform's native function calling capabilities to create intelligent assistants that can interact with external tools and APIs. This approach provides a more streamlined and robust implementation compared to manual ReAct pattern parsing.
While ReAct agents manually parse action patterns from text responses, OpenAI's native function calling provides:
import OpenAI from "openai"
import { getCurrentWeather, getLocation, tools } from "./tools"
export const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
dangerouslyAllowBrowser: true
})
const availableFunctions = {
getCurrentWeather,
getLocation
}
async function agent(query) {
const messages = [
{
role: "system",
content: "You are a helpful AI agent. Give highly specific answers based on information you're provided. Prefer to gather information with tools provided to you rather than giving basic, generic answers."
},
{ role: "user", content: query }
]
const MAX_ITERATIONS = 5
for (let i = 0; i < MAX_ITERATIONS; i++) {
console.log(`Iteration #${i + 1}`)
const response = await openai.chat.completions.create({
model: "gpt-3.5-turbo-1106",
messages,
tools
})
const { finish_reason: finishReason, message } = response.choices[0]
const { tool_calls: toolCalls } = message
console.log(toolCalls)
messages.push(message)
if (finishReason === "stop") {
console.log(message.content)
console.log("AGENT ENDING")
return
} else if (finishReason === "tool_calls") {
for (const toolCall of toolCalls) {
const functionName = toolCall.function.name
const functionToCall = availableFunctions[functionName]
const functionArgs = JSON.parse(toolCall.function.arguments)
const functionResponse = await functionToCall(functionArgs)
console.log(functionResponse)
messages.push({
tool_call_id: toolCall.id,
role: "tool",
name: functionName,
content: functionResponse
})
}
}
}
}
await agent("What's the current weather in my current location?")
/**
Expected Output:
The current weather in New York is sunny with a temperature of 75°F.
*/
export async function getCurrentWeather({ location }) {
const weather = {
location,
temperature: "75",
forecast: "sunny"
}
return JSON.stringify(weather)
}
export async function getLocation() {
try {
const response = await fetch('https://ipapi.co/json/')
const text = await response.json()
return JSON.stringify(text)
} catch (err) {
console.log(err)
}
}
export const tools = [
{
type: "function",
function: {
name: "getCurrentWeather",
description: "Get current weather",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "The location from where to get weather"
}
},
required: ["location"]
}
}
},
{
type: "function",
function: {
name: "getLocation",
description: "Get user's current location",
parameters: {
type: "object",
properties: {}
}
}
},
]
Tools are defined using JSON Schema format:
{
type: "function",
function: {
name: "getCurrentWeather",
description: "Get current weather",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "The location from where to get weather"
}
},
required: ["location"]
}
}
}
The tools array is passed to the API:
const response = await openai.chat.completions.create({
model: "gpt-3.5-turbo-1106",
messages,
tools // ← Tools array passed here
})
OpenAI returns structured tool calls:
const { finish_reason: finishReason, message } = response.choices[0]
const { tool_calls: toolCalls } = message
// toolCalls structure:
[
{
id: "call_abc123",
type: "function",
function: {
name: "getCurrentWeather",
arguments: '{"location": "New York"}'
}
}
]
Execute the function and add result to conversation:
for (const toolCall of toolCalls) {
const functionName = toolCall.function.name
const functionToCall = availableFunctions[functionName]
const functionArgs = JSON.parse(toolCall.function.arguments)
const functionResponse = await functionToCall(functionArgs)
messages.push({
tool_call_id: toolCall.id,
role: "tool",
name: functionName,
content: functionResponse
})
}
| Aspect | ReAct | OpenAI Function Calling |
|---|---|---|
| Tool Selection | Manual text parsing | Automatic tool selection |
| Argument Extraction | Regex patterns | JSON schema validation |
| Error Handling | Manual parsing errors | Structured error responses |
| Reliability | Prone to parsing failures | More reliable |
| Complexity | Higher implementation complexity | Lower implementation complexity |
Query: "What's the current weather in my current location?"
tool_calls with getLocation functiongetLocation() returns user IP locationtool_calls with getCurrentWeather functiongetCurrentWeather({location: "New York"}) returns weatherfinish_reason: "stop" with final answertry {
const functionResponse = await functionToCall(functionArgs)
messages.push({
tool_call_id: toolCall.id,
role: "tool",
name: functionName,
content: functionResponse
})
} catch (error) {
messages.push({
tool_call_id: toolCall.id,
role: "tool",
name: functionName,
content: JSON.stringify({ error: error.message })
})
}
OpenAI can call multiple tools simultaneously:
// OpenAI might return multiple tool_calls in one response
for (const toolCall of toolCalls) {
// Execute each tool call
const functionResponse = await functionToCall(functionArgs)
// Add each response separately
}
Design tools that can be used conditionally:
export const tools = [
{
type: "function",
function: {
name: "searchDatabase",
description: "Search database for information",
parameters: {
type: "object",
properties: {
query: { type: "string" },
filters: { type: "object" }
},
required: ["query"]
}
}
}
]
OpenAI function calling provides a more robust and reliable way to build AI agents compared to manual ReAct implementations, with better error handling, type safety, and integration with OpenAI ecosystem.
Note: OpenAI has introduced the new Responses API, which is an evolution of the Chat Completions API. The Responses API brings added simplicity and powerful agentic primitives to your integrations.
Key improvements in the Responses API:
As this API matures, future implementations should migrate to the Responses API for the most current and capable agent development experience.
// Future implementation will use Responses API
// (API subject to change as it evolves)
const response = await openai.responses.create({
// Enhanced parameters for better agent capabilities
})
ReAct Agents
ReAct (Reasoning and Acting) is a powerful agent pattern that combines the reasoning capabilities of Large Language Models with the ability to take actions through tools. This approach allows agents to break down complex problems, gather necessary information, and provide accurate responses.
Context Engineering
Understanding and managing context windows in large language models.