-
-
Notifications
You must be signed in to change notification settings - Fork 73
Description
Description
Active Agent documentation claims tools support a "universal common format" that works across all providers.
However, Active Agent 1.0.0 does NOT transform tools, causing OpenAI agents to fail with API errors when
using the documented common format.
Documentation vs Reality
Documentation claims (Tools Guide):
ActiveAgent supports a universal common format that works across all providers. Here's the reusable
pattern:
WEATHER_TOOL = {
name: "get_weather",
description: "Get current weather for a location",
parameters: {
type: "object",
properties: { ... }
}
}This same definition works identically with Anthropic, OpenAI, Ollama, and OpenRouter without modification.
Reality: Tools are NOT transformed. OpenAI agents fail.
Steps to Reproduce
- Create an agent using OpenAI with the documented common format:
class MyAgent < ApplicationAgent
generate_with :openai,
api_version: :chat,
instructions: { template: :instructions }
def respond
prompt(messages: build_messages, tools: my_tools)
end
private
def my_tools
[{
name: "fetch_data",
description: "Fetch some data",
parameters: {
type: "object",
properties: {
query: { type: "string", description: "Search query" }
},
required: ["query"]
}
}]
end
end- Call the agent
- OpenAI API returns error
Expected Behavior
Tools should be transformed to provider-native format automatically, as documented.
Actual Behavior
Error: Missing required parameter: 'tools[0].type'
Status: 400
Body: {
error: {
message: "Missing required parameter: 'tools[0].type'.",
type: "invalid_request_error",
param: "tools[0].type",
code: "missing_required_parameter"
}
}Root Cause Analysis
OpenAI requires wrapped format:
{
type: "function", # ← Required by OpenAI
function: {
name: "fetch_data",
description: "...",
parameters: { ... } # ← OpenAI uses "parameters"
}
}Anthropic accepts common format:
{
name: "fetch_data",
description: "...",
input_schema: { ... } # ← Anthropic uses "input_schema"
}Active Agent transform modules do NOT handle tools:
- Anthropic (lib/active_agent/providers/anthropic/transforms.rb):
- Line 27-32: normalize_params only handles messages and system
- No tool transformation - OpenAI (lib/active_agent/providers/open_ai/chat/transforms.rb):
- Line 32-48: normalize_params only handles instructions, messages, and response_format
- No tool transformation
Why it appears to work with Anthropic:
The Anthropic API natively accepts the common format, so no transformation is needed. This creates the false
impression that the common format "works" - but it's actually the API, not Active Agent, doing the work.
Impact
This affects any application using:
- Multiple providers (forces provider-specific tool definitions)
- OpenAI provider (must use native format, can't follow docs)
- Tool definitions in shared modules (can't reuse across providers)
Suggested Fix
Add tool transformation to both providers:
Option 1: Transform in normalize_params
lib/active_agent/providers/open_ai/chat/transforms.rb
def normalize_params(params)
params = params.dup
# Existing transformations...
params[:messages] = normalize_messages(params[:messages]) if params[:messages]
params[:response_format] = normalize_response_format(params[:response_format]) if params[:response_format]
# NEW: Transform tools to OpenAI format
params[:tools] = normalize_tools(params[:tools]) if params[:tools]
params
end
def normalize_tools(tools)
return tools unless tools.is_a?(Array)
tools.map do |tool|
# Already in OpenAI format? Pass through
next tool if tool[:type] == "function" && tool[:function]
# Convert common format to OpenAI format
{
type: "function",
function: {
name: tool[:name],
description: tool[:description],
parameters: tool[:parameters] || tool[:input_schema] # Support both keys
}.compact
}
end
endOption 2: Transform in api_request_build
Add tool transformation in BaseProvider#api_request_build before serialization.
Workaround
We're currently using provider-specific tool formats:
OpenAI agents:
def my_tools
[{
type: "function",
function: {
name: "fetch_data",
description: "...",
parameters: { ... }
}
}]
endAnthropic agents:
def my_tools
[{
name: "fetch_data",
description: "...",
input_schema: { ... }
}]
endThis prevents tool reuse across providers.
Environment
- Active Agent version: 1.0.0
- Ruby version: 3.4.7
- Rails version: 8.0.3
- Affected providers: OpenAI (openai gem 0.36.1)
- Working providers: Anthropic (anthropic gem 1.16.0)