Skip to content

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

Sakana2API

OpenAI-compatible API gateway for https://chat.sakana.ai.

It reverse-engineers the Sakana Chat web API and exposes it as a standard /v1/chat/completions endpoint, so you can use Sakana agents with any OpenAI-compatible client (OpenAI Python/JS SDK, ChatGPT-Next-Web, LobeChat, etc.).

Features

  • OpenAI-compatible endpoints
    • GET /v1/models
    • GET /v1/models/{model_id}
    • POST /v1/chat/completions (streaming & non-streaming)
  • Automatic model discovery via Sakana's /api/agents
  • Supports all Sakana Chat agents plus tone-mode and thinking variants
  • .env configuration for session cookie, Cloudflare clearance, proxy, etc.
  • Automatic cookie extraction from HAR files — no manual copy/paste needed
  • Runtime cookie reload / HAR upload endpoints
  • Automatic cookie refresh — upstream Set-Cookie headers are synced back and persisted
  • Automatic retry on 401/429 — reloads cookies and retries with exponential backoff
  • Optional gateway-level API key
  • HTTP/HTTPS proxy support for upstream requests
  • Thinking / planning chain exposed as reasoning_content

Prerequisites

  • Python >= 3.10
  • A Sakana Chat session cookie (sakana-chat) from your browser

Installation

# Create a virtual environment (recommended)
python -m venv .venv

# Windows
.venv\Scripts\python -m pip install -e .

# macOS / Linux
source .venv/bin/activate
pip install -e .

Configuration

Copy the example environment file and edit it:

cp .env.example .env

Required:

Variable Required Description
SAKANA_SESSION No* Value of the sakana-chat cookie
SAKANA_HAR_PATH No* Path to a HAR file for automatic cookie extraction

* At least one of SAKANA_SESSION or a HAR file is required.

Optional:

Variable Default Description
CF_CLEARANCE - Cloudflare clearance cookie (also auto-extracted from HAR)
API_KEY - Protect this gateway with a Bearer token
SAKANA_BASE_URL https://chat.sakana.ai Upstream base URL
DEFAULT_AGENT_ID namazu Fallback agent/model id
HTTP_PROXY / HTTPS_PROXY - Proxy for upstream requests. When set, SSL verification is disabled by default.
VERIFY_SSL auto true/false. Defaults to false when a proxy is configured, true otherwise.
COOKIE_STORE_PATH cookies.json File where refreshed cookies are persisted
MAX_RETRIES 2 Retries on upstream 401/429 with cookie reload and exponential backoff
HOST 0.0.0.0 Gateway bind address
PORT 8000 Gateway port
WORKERS 1 Uvicorn workers
REQUEST_TIMEOUT 120.0 Upstream request timeout (seconds)

Automatic cookie refresh

Sakana Chat re-issues the sakana-chat session cookie on almost every response (sliding expiration). The gateway watches upstream Set-Cookie headers and automatically updates the runtime cookie cache, then persists it to cookies.json.

  • Cookies loaded from .env or a HAR file are used as the initial seed.
  • Whenever Sakana returns a new sakana-chat or cf_clearance, it is saved to COOKIE_STORE_PATH (default: cookies.json).
  • On restart, the gateway loads .env first, then overlays the persisted cookies.json, so refreshed cookies survive restarts.

Note: This only extends the life of a valid session. If the upstream session is fully invalidated (401 ログインが必要です), you still need to re-export a HAR file or update SAKANA_SESSION manually.

Automatic retry on 401 / 429

When Sakana returns 401 Unauthorized or 429 Too Many Requests, the gateway automatically:

  1. Reloads cookies from .env / cookies.json / HAR
  2. Waits with exponential backoff (1s, 2s, 4s… capped at 8s)
  3. Retries the upstream request

Configure the retry count with MAX_RETRIES (default: 2). If all retries fail, the gateway returns 502 Bad Gateway with the upstream error message.

Option A: Automatic cookie extraction from HAR (recommended)

The gateway can read cookies directly from a browser HAR file, so you don't need to copy/paste them manually.

  1. Open https://chat.sakana.ai in your browser and log in.
  2. Open DevTools -> Network -> right-click -> Save all as HAR with content.
  3. Put the .har file in the project root (or set SAKANA_HAR_PATH).
  4. Start the gateway.

It will automatically pick up the latest sakana-chat and cf_clearance cookies from the HAR file.

# Optional: explicit HAR path
SAKANA_HAR_PATH=./chat.sakana.ai.har

Option B: Manual cookie copy

  1. Open https://chat.sakana.ai in your browser and log in.
  2. Press F12 -> Application (or Storage in Firefox) -> Cookies -> https://chat.sakana.ai.
  3. Find the cookie named sakana-chat and copy its value.
  4. Paste it into .env:
SAKANA_SESSION=3ff0203c-5a05-436e-a180-2060bfd00c08

The cookie is usually valid for ~14 days. If requests start failing with 403/401, refresh the cookie.

Usage

Start the server

# Using the installed script
sakana2api

# Or directly
python main.py

# Or with uvicorn
uvicorn sakana2api.app:app --host 0.0.0.0 --port 8000

Call with the OpenAI Python SDK

from openai import OpenAI

client = OpenAI(
    api_key="not-needed",  # or set to the API_KEY you configured
    base_url="http://127.0.0.1:8000/v1",
)

response = client.chat.completions.create(
    model="namazu",  # or any model id from GET /v1/models
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello!"},
    ],
    stream=False,
)
print(response.choices[0].message.content)

# Tone-mode variants are exposed as separate model ids.
# Use `namazu-jp-vibes` or `namazu-osaka` for different tones.
response = client.chat.completions.create(
    model="namazu-osaka",
    messages=[{"role": "user", "content": "こんにちは"}],
)

Streaming

stream = client.chat.completions.create(
    model="namazu",
    messages=[{"role": "user", "content": "Count to 5"}],
    stream=True,
)
for chunk in stream:
    content = chunk.choices[0].delta.content
    if content:
        print(content, end="")

Model variants

Sakana Chat exposes one agent (namazu) with several tone presets. The gateway maps these to OpenAI-style model ids:

Model id Agent Tone mode Thinking
namazu namazu default off
namazu-jp-vibes namazu jp-vibes off
namazu-osaka namazu osaka off
namazu-thinking namazu default on

Combined suffixes are also supported, e.g. namazu-osaka-thinking.

Thinking / reasoning chain

When thinking is enabled, Sakana may wrap its reasoning in <think>...</think> (or <plan>...</plan>) and put the final answer after it. The gateway can expose that reasoning chain as reasoning_content:

response = client.chat.completions.create(
    model="namazu-thinking",
    messages=[{"role": "user", "content": "Solve 23 * 47 step by step"}],
)
print(response.choices[0].message.reasoning_content)
print(response.choices[0].message.content)

To get the reasoning chain while using a non-thinking model, pass returnPlan: true:

response = client.chat.completions.create(
    model="namazu",
    messages=[{"role": "user", "content": "Explain quantum computing"}],
    extra_body={"returnPlan": True, "returnReasoning": True},
)

Sakana-specific options

You can override the model-derived defaults by passing extra body fields:

response = client.chat.completions.create(
    model="namazu",
    messages=[{"role": "user", "content": "Explain quantum computing"}],
    extra_body={
        "enableThinking": True,
        "toneMode": "default",
        "webSearchEnabled": True,
        "returnPlan": False,
        "returnReasoning": True,
    },
)
Option Type Default Description
enableThinking bool false Enable thinking mode
toneMode str "default" Tone preset (default, jp-vibes, osaka)
webSearchEnabled bool true Allow web search
returnPlan bool false Request a <plan> reasoning section
returnReasoning bool true Include extracted reasoning in reasoning_content

Note: Thinking mode and web search cannot be enabled at the same time upstream. When thinking is enabled, web search is automatically disabled unless you explicitly set webSearchEnabled: true.

Runtime Cookie Management

If API_KEY is set, these admin endpoints are protected by it.

Endpoint Method Description
POST /v1/admin/cookies JSON body Set cookies at runtime (sakana_chat, sakana_session, or cf_clearance)
POST /v1/admin/reload-cookies - Reload cookies from .env / HAR file
POST /v1/admin/upload-har Raw HAR bytes Upload a new HAR and extract cookies

Example:

curl -X POST http://127.0.0.1:8000/v1/admin/reload-cookies \
  -H "Authorization: Bearer your-api-key"

API Mapping

OpenAI endpoint Sakana endpoint
GET /v1/models GET /api/agents
POST /v1/chat/completions POST /conversation + POST /conversation/{id}

The gateway creates a fresh upstream conversation for every OpenAI request and embeds the full message history in the latest user turn, keeping the OpenAI side stateless.

Project Structure

sakana2api/
├── sakana2api/
│   ├── __init__.py
│   ├── app.py             # FastAPI routes
│   ├── config.py          # .env configuration & runtime cookie cache
│   ├── cookie_loader.py   # HAR / env cookie extraction
│   ├── formatter.py       # OpenAI -> Sakana message conversion
│   ├── main.py            # CLI entry point
│   ├── models.py          # Pydantic request/response models
│   ├── openai.py          # OpenAI response builders & streaming
│   ├── upstream.py        # Sakana upstream HTTP client
│   └── uuid7.py           # UUIDv7 generator for upstream message ids
├── main.py             # Backward-compatible entry point
├── .env.example
├── pyproject.toml
└── README.md

Error responses

When the upstream request fails, the gateway returns 502 Bad Gateway with a structured JSON body so you can tell what went wrong:

{
  "error": {
    "message": "Upstream authentication failed for /api/agents. ...",
    "code": "authentication_failed",
    "attempts": 3,
    "upstream_status": 401,
    "upstream_body": "..."
  }
}
code Meaning Typical fix
connection_failed Cannot reach Sakana (network, proxy, SSL) Check HTTP_PROXY/HTTPS_PROXY; set VERIFY_SSL=false if your proxy inspects SSL
authentication_failed Upstream returned 401 Refresh SAKANA_SESSION or upload a new HAR file
rate_limited Upstream returned 429 Wait for quota reset, or use a different account/cookie
invalid_response Upstream returned non-JSON or unexpected shape Usually a temporary Sakana API change; report an issue
upstream_error Any other upstream 4xx/5xx Inspect upstream_status and upstream_body

attempts shows how many times the gateway retried (including the initial request). MAX_RETRIES controls how many automatic retries are attempted on 401/429.

Troubleshooting

Symptom Cause / Fix
401/403 from upstream SAKANA_SESSION expired or missing. Refresh the cookie from your browser.
429 / usage limit The upstream account has hit its rate/conversation limit. Wait or refresh the cookie.
Cloudflare challenge Add CF_CLEARANCE cookie value to .env.
SSL certificate errors Set VERIFY_SSL=false if you are behind an SSL-inspecting proxy.
Timeouts Increase REQUEST_TIMEOUT or check your proxy.
Unknown model The model id is mapped to the Sakana agentId. Unknown ids fall back to DEFAULT_AGENT_ID.

Disclaimer

This is an unofficial community gateway. It is not affiliated with Sakana AI. Use at your own risk and in compliance with Sakana's Terms of Service.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages