openrouter-debug-bundle
Generates diagnostic reports for OpenRouter issues, capturing request/response cycles and metadata for troubleshooting.
Install
mkdir -p .claude/skills/openrouter-debug-bundle && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/7274" && unzip -o skill.zip -d .claude/skills/openrouter-debug-bundle && rm skill.zipInstalls to .claude/skills/openrouter-debug-bundle
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Create debug bundles for troubleshooting OpenRouter API issues. UseKey capabilities
- →Generate structured debug bundles containing request and response data
- →Correlate API failures using generation IDs
- →Verify environment and API key status
- →Capture full HTTP transcripts for troubleshooting
- →Extract generation metadata including latency and provider details
How it works
The skill uses a Python generator to capture request details and environment info, while providing curl commands to extract generation IDs for metadata lookup.
Inputs & outputs
When to use openrouter-debug-bundle
- →Diagnose API request failures
- →Investigate high latency
- →Correlate generation IDs
- →Check system status
About this skill
OpenRouter Debug Bundle
Current State
!node --version 2>/dev/null || echo 'N/A'
!python3 --version 2>/dev/null || echo 'N/A'
Overview
When an OpenRouter request fails or returns unexpected results, you need a structured debug bundle: the exact request, response, headers, generation metadata, and environment info. The generation ID (gen-* prefix in response.id) is the key correlator -- it lets you look up exact cost, provider used, and latency via GET /api/v1/generation?id=.
Prerequisites
- An OpenRouter API key (
sk-or-v1-...) exported asOPENROUTER_API_KEY— see theopenrouter-install-authskill for setup curlandjqfor the quick-debug flow and the Common Debug Checks- Python 3.8+ with the
openaiandrequestspackages for the Debug Bundle Generator - A failing or suspect request you can reproduce — its
gen-*generation ID is what everything else correlates on
Instructions
- Rule out environment problems first with the Common Debug Checks: verify the key via
/api/v1/auth/key, confirm the model exists in/api/v1/models, and checkstatus.openrouter.ai. - Reproduce the failure with the Quick Debug: curl command —
curl -v ... | tee /tmp/openrouter-debug.txtcaptures request headers, response headers, and body in one transcript. - Extract the generation ID (
jq -r '.id') and queryGET /api/v1/generation?id=$GEN_IDto get exact cost, token counts,generation_time, andprovider_name. - For failures inside an application, call
debug_request()from the Python Debug Bundle Generator to capture the same request/response/error/latency/environment data as aDebugBundleand save it withbundle.save("debug_bundle.json"). - Match the symptoms against the Error Handling table (missing generation ID, 502/503,
model_not_found, slow TTFT). - Before sharing a bundle, redact API keys per Enterprise Considerations (
sk-or-v1-...->sk-or-v1-[REDACTED]) and include the generation ID in any OpenRouter support request.
Quick Debug: curl
# Send a request and capture full response with headers
curl -v https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-H "HTTP-Referer: https://my-app.com" \
-H "X-Title: debug-test" \
-d '{
"model": "openai/gpt-4o-mini",
"messages": [{"role": "user", "content": "Say hello"}],
"max_tokens": 50
}' 2>&1 | tee /tmp/openrouter-debug.txt
# Extract generation ID from response
GEN_ID=$(jq -r '.id' /tmp/openrouter-debug.txt 2>/dev/null)
echo "Generation ID: $GEN_ID"
# Look up generation metadata (exact cost, provider, latency)
curl -s "https://openrouter.ai/api/v1/generation?id=$GEN_ID" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" | jq '.data | {
model: .model,
total_cost: .total_cost,
tokens_prompt: .tokens_prompt,
tokens_completion: .tokens_completion,
generation_time: .generation_time,
provider: .provider_name
}'
Python Debug Bundle Generator
import os, json, time, platform, sys
from datetime import datetime, timezone
from dataclasses import dataclass, asdict
from typing import Optional
from openai import OpenAI, APIError
import requests as http_requests
@dataclass
class DebugBundle:
timestamp: str
generation_id: Optional[str]
request_model: str
request_messages: list
request_params: dict
response_status: str
response_model: Optional[str]
response_content: Optional[str]
error_type: Optional[str]
error_message: Optional[str]
error_code: Optional[int]
latency_ms: float
generation_metadata: Optional[dict]
environment: dict
def to_json(self) -> str:
return json.dumps(asdict(self), indent=2)
def save(self, path: str = "debug_bundle.json"):
with open(path, "w") as f:
f.write(self.to_json())
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
default_headers={"HTTP-Referer": "https://my-app.com", "X-Title": "my-app"},
)
def debug_request(
messages: list[dict],
model: str = "openai/gpt-4o-mini",
**kwargs,
) -> DebugBundle:
"""Execute a request and capture everything for debugging."""
env = {
"python": sys.version,
"platform": platform.platform(),
"openai_sdk": getattr(__import__("openai"), "__version__", "unknown"),
}
start = time.monotonic()
gen_id = None
response_model = None
content = None
error_type = None
error_msg = None
error_code = None
status = "success"
gen_meta = None
try:
response = client.chat.completions.create(
model=model, messages=messages, **kwargs
)
gen_id = response.id
response_model = response.model
content = response.choices[0].message.content
except APIError as e:
status = "error"
error_type = type(e).__name__
error_msg = str(e)
error_code = e.status_code
except Exception as e:
status = "error"
error_type = type(e).__name__
error_msg = str(e)
latency = (time.monotonic() - start) * 1000
# Fetch generation metadata if we have an ID
if gen_id:
try:
gen = http_requests.get(
f"https://openrouter.ai/api/v1/generation?id={gen_id}",
headers={"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}"},
timeout=5,
).json()
gen_meta = gen.get("data")
except Exception:
pass
return DebugBundle(
timestamp=datetime.now(timezone.utc).isoformat(),
generation_id=gen_id,
request_model=model,
request_messages=messages,
request_params={k: v for k, v in kwargs.items() if k != "messages"},
response_status=status,
response_model=response_model,
response_content=content,
error_type=error_type,
error_message=error_msg,
error_code=error_code,
latency_ms=round(latency, 1),
generation_metadata=gen_meta,
environment=env,
)
# Usage
bundle = debug_request(
[{"role": "user", "content": "Test"}],
model="anthropic/claude-3.5-sonnet",
max_tokens=100,
)
print(bundle.to_json())
bundle.save("debug_bundle.json")
Common Debug Checks
# 1. Verify API key is valid
curl -s https://openrouter.ai/api/v1/auth/key \
-H "Authorization: Bearer $OPENROUTER_API_KEY" | jq '.data | {label, usage, limit, is_free_tier}'
# 2. Check if model exists
MODEL="anthropic/claude-3.5-sonnet"
curl -s https://openrouter.ai/api/v1/models | jq --arg m "$MODEL" '.data[] | select(.id == $m) | {id, context_length}'
# 3. Check OpenRouter status
curl -s https://status.openrouter.ai/api/v2/status.json | jq '.status'
Output
Running these flows leaves you with concrete debug artifacts:
/tmp/openrouter-debug.txt— the full verbose curl transcript (request/response headers plus the completion JSON) from the quick-debug step- A generation-metadata JSON from
/api/v1/generation:model,total_cost,tokens_prompt,tokens_completion,generation_time, andprovider_name debug_bundle.json— the serializedDebugBundle: timestamp, generation ID, request model/messages/params, response status and content, error type/message/code,latency_ms, generation metadata, and environment info (Python version, platform, SDK version)- One-line JSON results from the three Common Debug Checks (key label/usage/limit, model existence, OpenRouter status)
Examples
Looking up a request you just sent by its generation ID:
curl -s "https://openrouter.ai/api/v1/generation?id=$GEN_ID" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" | jq '.data | {model, total_cost, generation_time, provider: .provider_name}'
{
"model": "openai/gpt-4o-mini",
"total_cost": 0.000021,
"generation_time": 412,
"provider": "OpenAI"
}
If the metadata comes back empty, wait 1-2 seconds and retry with the same key that made the request. More worked examples: references/examples.md.
Error Handling
| Error | Cause | Fix |
|---|---|---|
| No generation ID in response | Request failed before reaching provider | Check network, verify base URL is https://openrouter.ai/api/v1 |
| Generation metadata missing | Fetched too soon or wrong key | Wait 1-2s; use same API key that made the request |
| Intermittent 502/503 | Upstream provider outage | Check status.openrouter.ai; try different provider |
model_not_found | Model ID typo or model removed | Query /api/v1/models to verify model exists |
| Slow TTFT (>10s) | Model cold start or overload | Use streaming; try :floor variant for different provider |
Enterprise Considerations
- Always redact API keys from debug bundles before sharing (
sk-or-v1-...->sk-or-v1-[REDACTED]) - Include the generation ID when contacting OpenRouter support -- it's the primary lookup key
- Log debug bundles to structured storage for post-incident analysis
- Set up automated debug bundle capture on 4xx/5xx responses in production
- Compare failing requests against a known-good baseline to isolate changes
References
- Examples | Errors
- Generation API | Status
When not to use it
- →When the request does not return a generation ID
- →When the API key is not properly exported
Prerequisites
Limitations
- →Generation metadata may be missing if fetched too soon
- →Requires manual redaction of API keys before sharing bundles
How it compares
Unlike manual logging, this workflow correlates specific generation IDs with provider-side metadata to isolate failures.
Compared to similar skills
openrouter-debug-bundle side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| openrouter-debug-bundle (this skill) | 1 | 27d | Caution | Intermediate |
| clojure-write | 16 | 3mo | No flags | Intermediate |
| codex-code-review | 1 | 8mo | Review | Intermediate |
| dead-code | 1 | 7mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
clojure-write
metabase
Guide Clojure and ClojureScript development using REPL-driven workflow, coding conventions, and best practices. Use when writing, developing, or refactoring Clojure/ClojureScript code.
codex-code-review
tyrchen
Perform comprehensive code reviews using OpenAI Codex CLI. This skill should be used when users request code reviews, want to analyze diffs/PRs, need security audits, performance analysis, or want automated code quality feedback. Supports reviewing staged changes, specific files, entire directories, or git diffs.
dead-code
parcadei
Find unused functions and dead code in the codebase
replit-advanced-troubleshooting
jeremylongshore
Apply Replit advanced debugging techniques for hard-to-diagnose issues. Use when standard troubleshooting fails, investigating complex race conditions, or preparing evidence bundles for Replit support escalation. Trigger with phrases like "replit hard bug", "replit mystery error", "replit impossible to debug", "difficult replit issue", "replit deep debug".
monggle-smart-qa
loboking
|
obsidian-observability
jeremylongshore
Set up comprehensive logging and monitoring for Obsidian plugins. Use when implementing debug logging, tracking plugin performance, or setting up error reporting for your Obsidian plugin. Trigger with phrases like "obsidian logging", "obsidian monitoring", "obsidian debug", "track obsidian plugin".