Implementation guide
Sakana Fugu API quickstart
A copyable integration is useful only if it fails clearly, keeps retries bounded, and captures the billable orchestration work. This walkthrough does all three without inventing unsupported parameters.
1. Choose the model before you write the request
The API surface is shared, but routing control, price predictability, access, and intended workload differ. Treat model choice as configuration, not a magic quality switch.
| Model ID | Use it for | Important constraint |
|---|---|---|
fugu | Interactive coding, chat, normal reviews, first evaluation pass | Pay-as-you-go cost varies with the routed model; specific agents may be excluded |
fugu-ultra | Difficult multi-step reasoning where quality is worth added time and cost | Fixed full agent pool; current docs say one to three agents |
fugu-ultra-20260615 | Pinning the documented dated Ultra version | Use the stable ID unless version pinning is a deliberate requirement |
fugu-cyber | Authorized defensive security reasoning and investigation | Pay-as-you-go only and returned only when access is approved |
Call GET /v1/models during setup rather than assuming a model ID is available to every key. That boundary check turns an ambiguous generation failure into a precise deployment error.
2. Validate configuration at startup
Secrets belong in environment variables. Missing values should stop the program immediately with the exact variable name, not surface later as a vague authentication or URL error.
import os
from openai import OpenAI
def require_environment_value(name: str) -> str:
value = os.environ.get(name, "").strip()
if not value:
raise RuntimeError(f"Missing required environment variable: {name}")
return value
def create_fugu_client() -> OpenAI:
base_url = require_environment_value("FUGU_BASE_URL").rstrip("/")
if not base_url.endswith("/v1"):
base_url += "/v1"
return OpenAI(
api_key=require_environment_value("FUGU_API_KEY"),
base_url=base_url,
timeout=120.0,
max_retries=2,
)
A small bounded retry count can absorb a transient connection or rate-limit response. An unbounded loop can repeat an expensive autonomous task, hide a persistent outage, and make the caller impossible to reason about.
3. Prefer the Responses API for new integrations
Sakana AI currently supports Responses, Chat Completions, and Models endpoints. Its model documentation recommends Responses for tool use, multimodal input, reasoning controls, and function calls.
from client import create_fugu_client
def review_change(change_description: str) -> str:
if not change_description.strip():
raise ValueError("change_description must not be empty")
response = create_fugu_client().responses.create(
model="fugu",
instructions="Find correctness risks first. State uncertainty explicitly.",
input=change_description,
max_output_tokens=2000,
)
return response.output_text
print(review_change("Review this database migration for rollback risks."))
The input check is intentionally local. It prevents an empty, billable request and provides a specific error before the network boundary.
4. Stream long responses without losing the final object
Streaming improves perceived latency, but the final response object is still important because that is where you inspect status and usage. Do not discard it after printing text deltas.
from client import create_fugu_client
def stream_answer(prompt: str):
client = create_fugu_client()
with client.responses.stream(model="fugu-ultra", input=prompt) as stream:
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)
return stream.get_final_response()
final_response = stream_answer("Compare two rollback plans and show failure modes.")
print()
print(final_response.usage)
If a caller disconnects, decide whether the server should cancel the upstream work. Do not automatically submit the same task again unless the operation is safe to repeat and the prior request is known not to have completed.
5. Know which OpenAI-shaped fields behave differently
Compatibility describes the request shape, not identical semantics. The current Sakana model page documents these differences.
| Field or behavior | Current documented behavior | Integration consequence |
|---|---|---|
temperature | Accepted but ignored on Responses | Do not build quality controls around it |
top_p, penalties, seed, stop | Accepted but ignored on Chat Completions | Validate required determinism with actual outputs |
previous_response_id | Not accepted | Send the full conversation history in input |
max_output_tokens | For Ultra, limits the final model output, not the orchestrator's own maximum | It is not a complete cost ceiling |
reasoning.effort | Supports high, xhigh, and max; xhigh and max are aliases | Do not assume three distinct effort levels |
| Built-in web search | Supported through the Responses tool shape | Test citation and tool output handling before production |
6. Capture all billable usage fields
For Ultra and Cyber, Sakana AI documents orchestration token details outside the usual input and output fields. It states that these represent real usage and count toward final price at the same category rate.
{
"input_tokens": 120,
"output_tokens": 80,
"input_tokens_details": {
"cached_tokens": 0,
"orchestration_input_tokens": 450,
"orchestration_input_cached_tokens": 100
},
"output_tokens_details": {
"orchestration_output_tokens": 220
}
}
For cost accounting, add normal and orchestration input, add normal and orchestration output, and add normal and orchestration cached input. Store raw usage beside your calculated estimate so later pricing or interpretation changes remain auditable.
See the exact formula and examples7. Turn common failures into specific actions
401 or 403
Check that the key is present, active, and tied to the expected billing mode. For Cyber, confirm that access was approved. Never log the secret itself.
404 model not found
Call the Models API with the same key and base URL. Fail startup with the missing model ID instead of silently switching to a different model.
429 rate limit
Respect any retry guidance, keep the total attempt count bounded, and surface the final error. Queueing can help, but a queue must also have a capacity and expiry policy.
Timeout
Separate connect time from task time in logs. A hard multi-agent task may legitimately take longer, but a larger timeout is not a substitute for cancellation, observability, or a user-visible status.
Unexpected cost
Compare the full usage object with the pricing formula. Check orchestration fields and whether requests exceeded 272K context. Do not infer cost from visible answer length alone.
Good-looking but wrong output
Do not retry blindly. Save the prompt, tools, model ID, and response ID; score it against a fixed rubric and route high-risk tasks to human review.
8. Production readiness checklist
- API key and base URL are required and validated at startup.
- The selected model is verified through
/v1/models. - Timeouts and retries have explicit finite values.
- Requests are safe to retry or have an idempotency strategy at the application layer.
- Logs include model, duration, status, and request correlation ID, but never secrets or sensitive prompt content by default.
- The complete usage object is retained for cost reconciliation.
- Ignored fields are not presented to users as active controls.
- Fallback behavior is explicit: return a clear failure, or use a named approved fallback with a visible quality tradeoff.
- EU and EEA availability is checked against current official policy before deployment.
- Security testing uses Cyber only with approved access, authorization, and a written scope.
Sources and verification boundary
- Sakana AI Models documentation: IDs, endpoints, supported fields, examples, and usage details
- Sakana AI Pricing documentation: billing modes and token rates
- Sakana AI Fugu product page: model positioning, agent opt-outs, and availability
This page describes documented behavior, not a private compatibility certification. Recheck the official Models endpoint and documentation before a production release.