Raw Client Integration (OpenAI & Anthropic)
Use LongGuard directly with the OpenAI or Anthropic Python SDK — no LangGraph or LangChain required.
How It Works
LongGuard v0.1.3 adds two class methods to AgentStep that extract all necessary
information from a raw SDK response using duck-typing (no hard SDK dependency):
AgentStep.from_openai_response(response, step_number, *, observation=None, latency_ms=0.0)
AgentStep.from_anthropic_response(response, step_number, *, observation=None, latency_ms=0.0)
Both methods extract:
| Field | OpenAI | Anthropic |
|---|---|---|
thought |
choices[0].message.content |
All text content blocks joined |
action |
tool_calls[0].function.name |
First tool_use block name |
action_input |
Parsed JSON from tool_calls[0].function.arguments |
tool_use block input dict |
tokens_used |
usage.total_tokens |
usage.input_tokens + output_tokens |
OpenAI Example
import openai
from longguard import AgentStep, CircuitBreaker, GuardConfig
client = openai.OpenAI()
breaker = CircuitBreaker(GuardConfig(
model="gpt-4o", # enables dollar-cost tracking
max_cost_usd=0.50, # hard-kill if run exceeds $0.50
max_steps=30,
))
messages = [{"role": "user", "content": "Research and summarize AI trends in 2025."}]
observation = None
for i in range(1, 31):
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=[...], # your tool definitions
)
# One-line conversion
step = AgentStep.from_openai_response(
response,
step_number=i,
observation=observation,
)
decision = breaker.check(step)
if decision.action == "kill":
print(f"⛔ Halted: {decision.reason}")
break
elif decision.action == "reflect":
messages.append({"role": "system", "content": decision.inject_prompt})
if step.action is None:
break # agent gave final answer
# Run the tool and get the observation for next step
observation = your_tool_runner(step.action, step.action_input)
messages.append({"role": "tool", "content": observation})
print(breaker.report.summary())
# → Estimated Cost: $0.0143 USD (gpt-4o)
Anthropic Example
import anthropic
from longguard import AgentStep, CircuitBreaker, GuardConfig
client = anthropic.Anthropic()
breaker = CircuitBreaker(GuardConfig(
model="claude-sonnet-5-5",
max_cost_usd=0.50,
max_steps=30,
))
messages = [{"role": "user", "content": "Analyze this dataset and summarize key findings."}]
observation = None
for i in range(1, 31):
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=2048,
tools=[...],
messages=messages,
)
step = AgentStep.from_anthropic_response(
response,
step_number=i,
observation=observation,
)
decision = breaker.check(step)
if decision.action == "kill":
print(f"⛔ Halted: {decision.reason}")
break
elif decision.action == "reflect":
messages.append({"role": "user", "content": decision.inject_prompt})
if step.action is None:
break
observation = your_tool_runner(step.action, step.action_input)
messages.append({"role": "user", "content": [{"type": "tool_result", "content": observation}]})
print(breaker.report.summary())
Supported Models & Pricing
LongGuard's built-in pricing table was verified against official provider sources on 2026-10-09. It uses standard, uncached text-token prices at the base context tier. See the pricing sources and availability audit for supported providers, removals, retirement dates, and promotional price expiry dates.
The selected registry excludes GPT-4/Turbo, GPT-3.5 Turbo, the o-series, Gemini 2.5,
Command R+, and the March 2024 Command R releases. Use list_supported_models()
to check whether a model has a built-in price.
Long-context premiums, caching, batch/priority rates, multimodal usage, and tool fees
require user-supplied prices or separate accounting. Removed model IDs return None;
provide explicit rates when estimating historical usage or enterprise contracts.
from longguard import list_supported_models, compute_cost
# List all models with known pricing
print(list_supported_models())
# Includes 'claude-sonnet-5-5', 'gemini-3.8-flash', 'gpt-6.1-sol', ...
# Compute cost for a specific workload
cost = compute_cost("gpt-4o", input_tokens=10_000, output_tokens=3_000)
# $0.055
Pricing Resolution Order
- User-supplied —
cost_per_input_token+cost_per_output_tokeninGuardConfig - Built-in table — automatic lookup by
modelname (case-insensitive) - Graceful fallback —
estimated_cost_usd = Noneif model not recognised;max_cost_usdcap silently skipped
For models not yet in the table, supply your own prices:
config = GuardConfig(
cost_per_input_token=3e-6, # look up from provider pricing page
cost_per_output_token=15e-6,
max_cost_usd=1.00,
)
Runnable Example
A complete self-contained demo (runs without an API key via mock):
Stop with pending tool calls
Converters preserve their existing first-action summary. Cleanup must inspect the original provider conversation to preserve every tool call identifier:
from longguard.integrations.messages import resolve_pending_tool_calls
# First stop dispatching new tools. Append the actual assistant response to messages.
cleanup = resolve_pending_tool_calls(messages, decision.reason, protocol="openai")
messages = cleanup.messages
# Append cleanup.dispositions to your report if desired.
Use protocol="anthropic" for Anthropic tool-use blocks. Completed results remain unchanged;
unstarted calls receive failed/skipped results and never a fabricated success. If calls are
already running, pass running_ids={...}: they remain unresolved until real completion.
Do not continue the provider conversation with unresolved running calls. The helper itself
never cancels or executes tools, and assumes a valid conversation prefix.