# Proxy para API de Claude vía Sesión Web: Integración con OpenClaw y Uso de Herramientas
Anthropic ha bloqueado el uso de Claude en apps de terceros como OpenClaw. Los suscriptores Pro ($100/mes) recibieron $100 en créditos extra de uso, pero eso no soluciona la integración de agentes. ¿La solución? Un servidor proxy que imita una sesión de navegador de Claude.ai con una API compatible con OpenAI. Así puedes ejecutar Claude Sonnet/Opus en OpenClaw con soporte completo para herramientas.
Desarrollado en Python con curl_cffi para huella TLS de Chrome. Las cookies y el ID de dispositivo provienen de tu sesión activa. Cada solicitud inicia una conversación nueva, transmitiendo respuestas vía SSE.
Configuración Básica de Sesión y Encabezados
La sesión imita Chrome con cookies reales del navegador. Probado con el navegador antidetección Camoufox.
def make_session() -> cf_requests.Session:
"""Crea una nueva sesión curl_cffi con huella TLS de Chrome."""
cookies = get_cookies()
session = cf_requests.Session(impersonate=IMPERSONATE)
session.cookies.update(cookies)
return session
def get_headers(cookies: dict) -> dict:
return {
"User-Agent": (
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"
),
"Origin": "https://claude.ai",
"Referer": "https://claude.ai/new",
"anthropic-device-id": cookies.get("anthropic-device-id", ""),
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
}
Lógica de Solicitudes de Completado
- POST a
/api/organizations/{org_id}/chat_conversationspara crear una conversación. - POST a
/chat_conversations/{conv_id}/completioncontext/event-stream.
def claude_complete(
prompt: str,
internal_model: str,
) -> Generator[str, None, None]:
"""Generador síncrono que emite líneas SSE de completado de claude.ai."""
cookies = get_cookies()
org_id = cookies["lastActiveOrg"]
headers = get_headers(cookies)
session = make_session()
# 1. Crear conversación
r = session.post(
f"https://claude.ai/api/organizations/{org_id}/chat_conversations",
json={"uuid": None, "name": ""},
headers=headers,
timeout=15,
)
r.raise_for_status()
conv_id = r.json()["uuid"]
log.info(f"Conv creada: {conv_id} model={internal_model}")
# 2. Transmitir completado
payload = {
"prompt": prompt,
"model": internal_model,
"timezone": "Europe/Moscow",
"attachments": [],
"files": [],
}
r2 = session.post(
f"https://claude.ai/api/organizations/{org_id}/chat_conversations/{conv_id}/completion",
json=payload,
headers={**headers, "Accept": "text/event-stream"},
stream=True,
timeout=60,
)
r2.raise_for_status()
for line in r2.iter_lines():
yield line
El servidor API usa aiohttp con rutas para /v1/models, /v1/chat/completions, /health. Se ejecuta en 127.0.0.1:8787.
def make_app() -> web.Application:
app = web.Application()
app.router.add_get("/v1/models", handle_models)
app.router.add_get("/health", handle_health)
app.router.add_post("/v1/chat/completions", handle_chat_completions)
return app
Integración con OpenClaw
Configuración del proveedor:
"claude-web": {
"baseUrl": "http://127.0.0.1:8787/v1",
"apiKey": "dummy",
"api": "openai-completions",
"models": [
{
"id": "claude-sonnet-4-6-web",
"name": "Claude Sonnet 4.6 (Web)",
"reasoning": false,
"input": ["text"],
"cost": {"input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0},
"contextWindow": 200000,
"maxTokens": 32000
}
]
}
La generación de texto funciona de inmediato. El uso de herramientas requiere ajustes.
Soporte para Herramientas: Inyección de Prompt
El prompt del sistema obliga a Claude a generar llamadas a herramientas en formato XML:
TOOL_SYSTEM_PROMPT = """Tienes acceso a herramientas. Cuando necesites llamar a una herramienta, emite SOLO el bloque de llamada — sin explicaciones, sin texto antes o después:
<tool_call>
{{
"name": "tool_name_here", "arguments": {{"param1": "value1", "param2": "value2"}}
}}
</tool_call>
REGLAS:
- El JSON dentro de <tool_call> debe ser válido — sin comas finales, sin comentarios
- Puedes emitir múltiples bloques <tool_call> en secuencia
- Tras recibir bloques <tool_result>, continúa tu respuesta normalmente
- Si no llamas a una herramienta, responde normalmente sin etiquetas <tool_call>
Herramientas disponibles:
{tools_json}"""
El análisis usa regex con correcciones automáticas para errores JSON (comas finales, comentarios).
Manejo Final de Llamadas y Resultados de Herramientas
- El analizador extrae bloques
<tool_call>, corrige JSON y convierte al formato OpenAI. - Los resultados de herramientas se inyectan como XML
<tool_result id="...">contenido</tool_result>en mensajes de usuario.
def parse_tool_calls(text: str) -> tuple[list[dict], str]:
tool_calls = []
for match in TOOL_CALL_RE.finditer(text):
raw_json = match.group(1).strip()
obj = None
try:
obj = json.loads(raw_json)
except json.JSONDecodeError:
fixed = _try_fix_json(raw_json)
obj = json.loads(fixed)
if obj:
tool_calls.append({
"id": f"call_{uuid.uuid4().hex[:12]}",
"type": "function",
"function": {
"name": obj.get("name", ""),
"arguments": json.dumps(obj.get("arguments", {})),
},
})
remaining = TOOL_CALL_RE.sub("", text).strip()
return tool_calls, remaining
def inject_tool_results(messages: list[dict], tools: list[dict]) -> list[dict]:
# Convierte tool_calls/resultados OpenAI a XML para Claude
# ... (lógica de lotes y generación XML)
Características Principales
- Compatibilidad Total: API de OpenAI con uso de herramientas para OpenClaw/Claude Sonnet 4.6 (contexto de 200k).
- Modo Sigiloso: curl_cffi + cookies/ID de dispositivo reales, TLS de Chrome.
- Corrección Automática: Maneja fallos comunes de JSON de Claude (comas finales, comentarios).
- Transmisión: SSE desde API web, conversación nueva por solicitud.
- Límites: Respeta la suscripción Pro, sin uso extra.
Limitaciones y Mejoras
Depende de la estabilidad de la API web de Claude.ai. Posibles problemas:
- Captchas en el sitio.
- Tiempo de espera de sesiones.
- Cambios en endpoints.
Soluciones: Actualización automática de cookies, rotación de ID de dispositivo, manejo de errores.
— Editorial Team
Aún no hay comentarios.