Inbound webhooks — let external systems (Flowise, CI, GitHub) trigger your agent.
free-code opens a small local HTTP endpoint so external systems can push events into a running agent session.
MCP lets free-code call out to external tools. Inbound webhooks are the
opposite direction: an external system — a Flowise flow, a CI job, a
GitHub event — makes an HTTP POST to free-code, and that event either
lands in a queue the agent can read or wakes the agent to act on it
immediately.
sendUserMessage()),
so this ships as the built-in webhook-receiver extension, loaded
automatically in every session.
See an external system trigger a running agent session.
Register a named hook, hand its URL to the external system, receive its POSTs.
flowise) from inside free-code.POST http://127.0.0.1:<port>/hook/<name> and returns a secret.Each hook has a delivery mode:
| Mode | Behaviour | Best for |
|---|---|---|
queue |
The event is buffered. The agent drains it with poll_webhook_events or long-polls with wait_for_webhook_event. |
Predictable, on-demand consumption; noisy sources. |
trigger |
The event is injected as a message that starts a turn immediately (queued as a follow-up if the agent is mid-stream). | React-now events: a build failed, a flow finished. |
The direction of data, the end-to-end lifecycle, and what happens to each event.
queue buffers for later, trigger wakes the agent now.wait_for_webhook_event for the result.Register from the command line, or just ask the agent.
/webhook command (CLI)# Register a hook that wakes the agent on every event
/webhook add flowise --trigger
# Show its callback URL + secret again
/webhook url flowise
# List hooks and server status
/webhook list
# Peek at buffered events (queue mode)
/webhook events
# Force a specific port for this session
/webhook port 8790
# Remove a hook
/webhook rm flowise
Omit --trigger to create a queue hook. A secret is generated automatically.
The same actions are exposed as tools, so in the CLI, the IDE plugin, or the desktop app you can just say: "register a webhook called flowise in trigger mode and give me the URL."
/webhook command is also
listed in the plugin and desktop command catalogs.
Send a request with curl and watch the agent receive it.
After /webhook add test --trigger, take the URL and secret it printed, then:
# Replace the port and secret with what /webhook url test showed
curl -X POST http://127.0.0.1:8788/hook/test \
-H 'content-type: application/json' \
-H 'X-Webhook-Secret: <your-secret>' \
-d '{"msg":"hello from curl"}'
Expected: the request returns {"ok":true}, and in a trigger hook the agent wakes and reacts to the payload.
For a queue hook, drain what arrived:
/webhook events # or ask the agent to poll the webhook events
Auth is mandatory — a wrong or missing secret is rejected with 401:
curl -i -X POST http://127.0.0.1:8788/hook/test \
-H 'X-Webhook-Secret: wrong' -d '{}'
# HTTP/1.1 401 Unauthorized
There's also a liveness endpoint:
curl http://127.0.0.1:8788/health
# {"ok":true,"hooks":["test"]}
Local by default; every hook is authenticated.
127.0.0.1 by default — not reachable from the network.X-Webhook-Secret header (compared in constant time).hmacSecret and sign the raw body: X-Signature: sha256=<hex>.cloudflared tunnel --url http://127.0.0.1:8787 or
ngrok, set publicBaseUrl, and require HMAC.
Every free-code window gets its own port automatically.
Each session binds the first free port from 8787 upward
(8787, 8788, 8789, …), so several free-code
windows coexist without clashing. The callback URL always reflects the port a session
actually bound — check it with /webhook url <name>.
To pin a known port:
# Per session, live:
/webhook port 8790
# Or set it before launch:
FREECODE_WEBHOOK_PORT=8790 free-code
Tools, config file, and environment variables.
| Tool | What it does |
|---|---|
register_webhook | Create a named hook and return its callback URL + secret. |
unregister_webhook | Remove a hook. |
get_webhook_url | Show a hook's callback URL and auth hint. |
list_webhooks | List hooks, server status, and queued-event count. |
poll_webhook_events | Return (and by default drain) buffered events. |
wait_for_webhook_event | Long-poll until the next event or a timeout. |
register_external_webhook | POST free-code's callback URL into an external system's API. |
~/.free-code/agent/webhook-receiver.json{
"enabled": true,
"host": "127.0.0.1",
"port": 8787,
"portRange": 20,
"publicBaseUrl": null,
"defaultMode": "queue",
"maxBodyBytes": 1048576,
"hooks": {
"flowise": { "mode": "trigger", "secret": "…" }
}
}
| Variable | Effect |
|---|---|
FREECODE_WEBHOOK_ENABLED | Turn the receiver on/off. |
FREECODE_WEBHOOK_PORT | Base port to bind. |
FREECODE_WEBHOOK_HOST | Bind host (default 127.0.0.1). |
FREECODE_WEBHOOK_PUBLIC_URL | Public base URL used in callback URLs (behind a tunnel). |
Webhooks entrantes — deja que sistemas externos (Flowise, CI, GitHub) activen a tu agente.
free-code abre un pequeño endpoint HTTP local para que sistemas externos puedan enviar eventos a una sesión de agente en ejecución.
MCP permite que free-code llame hacia afuera a herramientas externas. Los
webhooks entrantes son la dirección opuesta: un sistema externo — un flujo de
Flowise, un job de CI, un evento de
GitHub — hace un POST HTTP a free-code, y ese evento o bien
llega a una cola que el agente puede leer, o despierta al agente para que
actúe sobre él de inmediato.
sendUserMessage()), por eso esto se distribuye como la extensión
integrada webhook-receiver, cargada automáticamente en cada sesión.
Observa cómo un sistema externo activa una sesión de agente en ejecución.
Registra un hook con nombre, entrega su URL al sistema externo, recibe sus POSTs.
flowise) desde dentro de free-code.POST http://127.0.0.1:<port>/hook/<name> y devuelve un secreto.Cada hook tiene un modo de entrega:
| Modo | Comportamiento | Ideal para |
|---|---|---|
queue |
El evento se almacena en un búfer. El agente lo consume con poll_webhook_events o hace long-polling con wait_for_webhook_event. |
Consumo predecible y bajo demanda; fuentes ruidosas. |
trigger |
El evento se inyecta como un mensaje que inicia un turno de inmediato (se encola como seguimiento si el agente está en medio de una respuesta). | Eventos que requieren reacción inmediata: falló un build, terminó un flujo. |
La dirección de los datos, el ciclo de vida completo, y qué le pasa a cada evento.
queue lo almacena en búfer para después, trigger despierta al agente de inmediato.wait_for_webhook_event para el resultado.Regístralo desde la línea de comandos, o simplemente pídeselo al agente.
/webhook (CLI)# Registra un hook que despierta al agente en cada evento
/webhook add flowise --trigger
# Muestra de nuevo su URL de callback + secreto
/webhook url flowise
# Lista los hooks y el estado del servidor
/webhook list
# Revisa los eventos en búfer (modo queue)
/webhook events
# Fuerza un puerto específico para esta sesión
/webhook port 8790
# Elimina un hook
/webhook rm flowise
Omite --trigger para crear un hook queue. Se genera un secreto automáticamente.
Las mismas acciones se exponen como herramientas, así que en el CLI, el plugin del IDE, o la aplicación de escritorio puedes simplemente decir: "registra un webhook llamado flowise en modo trigger y dame la URL."
/webhook también aparece listado en los catálogos de comandos del plugin y
del escritorio.
Envía una solicitud con curl y observa cómo el agente la recibe.
Después de /webhook add test --trigger, toma la URL y el secreto que imprimió, luego:
# Reemplaza el puerto y el secreto con lo que mostró /webhook url test
curl -X POST http://127.0.0.1:8788/hook/test \
-H 'content-type: application/json' \
-H 'X-Webhook-Secret: <your-secret>' \
-d '{"msg":"hello from curl"}'
Esperado: la solicitud devuelve {"ok":true}, y en un hook trigger el agente despierta y reacciona al payload.
Para un hook queue, consume lo que llegó:
/webhook events # o pídele al agente que consulte los eventos del webhook
La autenticación es obligatoria — un secreto incorrecto o ausente se rechaza con 401:
curl -i -X POST http://127.0.0.1:8788/hook/test \
-H 'X-Webhook-Secret: wrong' -d '{}'
# HTTP/1.1 401 Unauthorized
También hay un endpoint de disponibilidad:
curl http://127.0.0.1:8788/health
# {"ok":true,"hooks":["test"]}
Local por defecto; cada hook está autenticado.
127.0.0.1 por defecto — no es alcanzable desde la red.X-Webhook-Secret (se compara en tiempo constante).hmacSecret y firma el cuerpo crudo: X-Signature: sha256=<hex>.cloudflared tunnel --url http://127.0.0.1:8787 o
ngrok, configura publicBaseUrl, y exige HMAC.
Cada ventana de free-code obtiene su propio puerto automáticamente.
Cada sesión se vincula al primer puerto libre a partir de 8787
(8787, 8788, 8789, …), de modo que varias
ventanas de free-code coexisten sin chocar entre sí. La URL de callback siempre refleja
el puerto que una sesión efectivamente vinculó — compruébalo con
/webhook url <name>.
Para fijar un puerto conocido:
# Por sesión, en vivo:
/webhook port 8790
# O configúralo antes de iniciar:
FREECODE_WEBHOOK_PORT=8790 free-code
Herramientas, archivo de configuración y variables de entorno.
| Herramienta | Qué hace |
|---|---|
register_webhook | Crea un hook con nombre y devuelve su URL de callback + secreto. |
unregister_webhook | Elimina un hook. |
get_webhook_url | Muestra la URL de callback de un hook y una pista de autenticación. |
list_webhooks | Lista los hooks, el estado del servidor, y el conteo de eventos en cola. |
poll_webhook_events | Devuelve (y por defecto vacía) los eventos en búfer. |
wait_for_webhook_event | Hace long-polling hasta el próximo evento o un tiempo de espera agotado. |
register_external_webhook | Hace POST de la URL de callback de free-code hacia la API de un sistema externo. |
~/.free-code/agent/webhook-receiver.json{
"enabled": true,
"host": "127.0.0.1",
"port": 8787,
"portRange": 20,
"publicBaseUrl": null,
"defaultMode": "queue",
"maxBodyBytes": 1048576,
"hooks": {
"flowise": { "mode": "trigger", "secret": "…" }
}
}
| Variable | Efecto |
|---|---|
FREECODE_WEBHOOK_ENABLED | Activa o desactiva el receptor. |
FREECODE_WEBHOOK_PORT | Puerto base al que vincularse. |
FREECODE_WEBHOOK_HOST | Host de vinculación (por defecto 127.0.0.1). |
FREECODE_WEBHOOK_PUBLIC_URL | URL base pública usada en las URLs de callback (detrás de un túnel). |