Webhooks entrantes
orch webhook serve: un receptor local verificado por HMAC que convierte un POST firmado en una tarea, desde n8n/Zapier, GitHub o Slack.
Objetivo#
Dejar que un disparador externo — un flujo de n8n/Zapier, un issue o
comentario de GitHub, un slash command de Slack — cree una tarea de Orchemax y,
una vez aprobada, la despache. orch webhook serve es un servidor HTTP local
pequeno, solo loopback por defecto, con tres rutas: /task, /github,
/slack. Es la contraparte entrante de orch notify (ver "Notificaciones y
aprobaciones"), que solo envia eventos hacia afuera.
Pasos#
-
Configura un secreto compartido y las rutas que quieras en
orch.yaml:webhook: secret_env: ORCH_WEBHOOK_SECRET allow: [task, github, slack] # omitir = las tres require_approval: true # default; false deja despachar de inmediato una peticion firmada templates: cursor: agent: cursor prompt: "Lee los PR abiertos y resume." timeout_sec: 300 github: # usado por eventos "issue opened/labelled orch" de GitHub agent: billingORCH_WEBHOOK_SECRETdebe estar definido en el entorno donde correorch webhook serve. Cada ruta verifica una firma calculada con ese mismo secreto, con su propio esquema (abajo). -
Arranca el servidor:
orch webhook serve --addr 127.0.0.1:8790El listener rechaza una direccion que no sea loopback (
0.0.0.0, un:8790sin host, una IP de LAN) salvo que pases--allow-remote— ponlo detras de tu propio reverse proxy/tunel si necesita ser alcanzable desde los servidores de GitHub o Slack. -
Verifica el cableado con una peticion firmada de muestra:
orch webhook test --route task --agent cursor --prompt "responde con ok" --dispatch --approve
POST /task#
Body (JSON): {"template": "cursor", "project": "...", "dispatch": true, "approve": false}
(o agent + prompt en vez de template). Headers:
X-Orch-Timestamp (segundos unix) y X-Orch-Signature — HMAC-SHA256 en hex
de "<timestamp>.<body crudo>" bajo el secreto compartido.
Respuesta: {"task_id", "status", "dispatched", "session_id"}. La tarea
siempre se crea; solo despacha cuando dispatch:true y ademas approve:true
o webhook.require_approval: false — si no, sale un evento needs_approval
por orch notify (webhooks/Telegram), y la tarea espera orch task run <id>
o una futura accion de aprobacion.
POST /github#
Verifica X-Hub-Signature-256 (el esquema propio de GitHub, HMAC-SHA256
sobre el body crudo). Dos eventos:
issues(opened, olabeledcon la etiquetaorch): crea una tarea a partir del titulo/body del issue usandowebhook.templates.github(agent y project salen de ese template — configuralo, o el evento se ignora).issue_comment(un comentario que empieza con/orch <template> <prompt extra>, en un issue o un PR): crea una tarea desdewebhook.templates.<template>, con el resto de la linea reemplazando el prompt por defecto del template.
Ambos despachan bajo la misma regla de require_approval que /task — un
evento crudo de GitHub no trae un campo approve, asi que solo corre de
inmediato cuando webhook.require_approval: false.
POST /slack#
Verifica el esquema de firma v0 de Slack: X-Slack-Request-Timestamp +
X-Slack-Signature: v0=<hex hmac(secret, "v0:"+timestamp+":"+body)>. El body
es el payload propio de Slack para slash commands,
application/x-www-form-urlencoded — el campo text es
<template> <prompt>. Responde 200 de inmediato con un ack efimero
({"response_type":"ephemeral","text":"..."}) que nombra el id de la tarea y
si despacho o quedo esperando aprobacion.
n8n#
Usa un nodo HTTP Request (no el trigger Webhook — ese es para recibir, aca
estas llamando hacia Orchemax). Apuntalo a http://<host>:8790/task, metodo
POST, body JSON, y agrega dos headers calculados en un nodo Function/Code
antes: X-Orch-Timestamp = unix time actual, X-Orch-Signature = HMAC-SHA256
en hex de "<timestamp>.<body>" con tu ORCH_WEBHOOK_SECRET. La mayoria de
los nodos de cripto/HMAC, o un Code node de una linea, cubren esto.
Zapier#
Usa la accion "Webhooks by Zapier", "Custom Request" (POST), misma URL y
body JSON. Calcula los dos headers con un paso "Code by Zapier" (Node.js
crypto.createHmac('sha256', secret)) justo antes del paso de webhook, ya
que Zapier no trae una accion HMAC propia.
Lo que nunca sale de la maquina#
Cada respuesta es solo JSON de estado/resumen — nada de codigo, contenido de archivo ni diff. El limite de 256 KB por body, el margen de 5 minutos en el timestamp y una cache de replay de 10 minutos (por firma) aplican a las tres rutas.