OpenAI Message Format¶
strahl.analyze() currently accepts OpenAI-style message dictionaries.
Call it after the assistant response that requests tool calls, before executing those tools.
from openai import OpenAI
import strahl
client = OpenAI()
messages = [{"role": "user", "content": "Find my order."}]
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=[...],
)
messages.append(response.choices[0].message.to_dict())
analysis = strahl.analyze(messages)
analysis.raise_if_denied()
OpenAI tool calls appear in the assistant message under tool_calls, with
arguments as a JSON string:
{
"role": "assistant",
"content": None,
"tool_calls": [
{
"id": "call_abc123",
"function": {
"name": "lookup_order",
"arguments": '{"order_id": "ord_123"}',
},
}
],
}
Tool results from earlier turns are role "tool" messages referencing the call
by tool_call_id:
Requirements¶
- The final trace item must be a pending assistant tool call.
- Every non-tool message role must have a role label.
- Every final tool call must reference a registered tool.
- Tool call arguments must be valid JSON objects.
Registering OpenAI Tool Schemas¶
import strahl
from strahl import Label
openai_tool = {
"type": "function",
"function": {
"name": "lookup_order",
"description": "Look up an order by ID.",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
},
}
strahl.add_tool(
fn=openai_tool,
requires=Label(source={"user"}, visibility={"user"}),
produces=Label(source={"orders"}, visibility={"user"}),
)