Research OpenRouter API docs, available Grok model IDs, vision capability for the judge service, and integration patterns. Use when implementing openrouter_tool.py, when checking which Grok model supports vision/image input for judge_service.py, when OpenRouter returns unexpected errors, or when verifying model availability and context limits.
Research current OpenRouter API specifications and Grok model availability for SFUMATO.
All text LLM calls in SFUMATO go through app/tools/openrouter_tool.py:
prompt_service.generate_prompt() — Grok, text-only inputprompt_service.revise_prompt() — Grok, text-only inputjudge_service.evaluate() — Grok with vision (must analyze generated image)ENV vars: OPENROUTER_API_KEY, OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
Client: httpx.AsyncClient — OpenAI-compatible API
Read existing file first if it exists:
app/tools/openrouter_tool.pyconfig.pyhttps://openrouter.ai/docs/api-reference/overviewhttps://openrouter.ai/docs/requestsOpenRouter API python httpx async chat completions 2025Capture:
https://openrouter.ai/api/v1Authorization: Bearer vs API-Key)HTTP-Referer, X-TitlePOST /v1/chat/completionsmodel, messages, temperature, max_tokens, streamchoices[0].message.contenthttps://openrouter.ai/models?q=grokOpenRouter xAI Grok models list 2025https://openrouter.ai/x-ai if availableFor each available Grok model, capture:
x-ai/grok-beta, x-ai/grok-vision-beta)Determine the best model for each use case:
prompt_gen: text-only, large contextprompt_revise: text-onlyjudge: MUST support vision/image inputSince judge_service.py sends a generated image to Grok for evaluation:
OpenRouter vision model image input base64 format 2025https://openrouter.ai/docs/features/visionOpenAI-compatible vision API image_url content type formatCapture:
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}
vs URL-based image referenceOpenRouter API error handling retry 429 503 2025https://openrouter.ai/docs/api-reference/errors if availableCapture:
retry-after header? fixed backoff interval?# Async httpx client structure
BASE_URL = "https://openrouter.ai/api/v1"
# Required headers
headers = {
"Authorization": f"Bearer {api_key}",
"HTTP-Referer": "...",
"X-Title": "SFUMATO",
"Content-Type": "application/json",
}
# chat_completion(model, messages, temperature, max_tokens) -> str
# vision_completion(model, text_messages_plus_image_message) -> str
# Retry pattern for 429/503 (show how many retries, backoff)
# Error handling: which codes to retry vs raise immediately
| Use Case | Recommended Model ID | Context | Vision | Notes |
|---|---|---|---|---|
| prompt_gen | x-ai/grok-... | N | No | |
| prompt_revise | x-ai/grok-... | N | No | |
| judge | x-ai/grok-... | N | YES | Required |
Exact Python dict structure to use when sending image to judge:
{
"role": "user",
"content": [
{"type": "text", "text": "...judge prompt..."},
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}
]
}
OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1"
OPENROUTER_MODEL_PROMPT_GEN = "x-ai/grok-..."
OPENROUTER_MODEL_PROMPT_REVISE = "x-ai/grok-..."
OPENROUTER_MODEL_JUDGE = "x-ai/grok-vision-..." # must support vision
OPENROUTER_TIMEOUT_TEXT = 30
OPENROUTER_TIMEOUT_VISION = 45
OPENROUTER_MAX_RETRIES = 2
data/sessions/<id>/iter_<n>.jpg, encode as base64vision_completion()HTTP-Referer should be "http://localhost:5000" for local dev