Lampson

Lampson como motor

API HTTP

Cada projeto (workspace) do Lampson expõe uma API para seus apps, seus bots e outros agentes:

https://seu-lampson/w/<workspace>/v1/…

Sem URL pública, a base é http://127.0.0.1:8080/w/<workspace>/v1 — só a partir deste computador. Para usar de fora: lampson --domain ou um túnel.

API keys§

A API pede sempre uma key, também a partir do mesmo computador.

lampson key add --agent tienda --name "bot do whatsapp"
lampson key add --agent tienda,soporte --rate 60 --callback https://hooks.mi-app.com/
lampson key list
lampson key remove k6KJgJHpu

Ou pela web: API no painel esquerdo → + crear una API key (“+ criar uma API key”).

  • A key é mostrada uma única vez, com as URLs da API e do MCP prontas para copiar. O Lampson guarda só o hash dela.
  • --agent: os agentes que ela pode usar (sem opção, todos).
  • --rate N: pedidos por minuto (padrão 120; 0 = sem limite). Passado o limite, responde 429 com Retry-After.
  • --callback URL: as únicas URLs para as quais o Lampson mandará callbacks com esta key: mesmo esquema, host e porta, e o caminho como pasta (https://app.com/hooks permite /hooks/…, não app.com.evil.net nem /hooks-x). Sem essa opção, a key não pode pedir callbacks. As keys criadas antes do Lampson 0.5.1 chegam a qualquer nome de host público, e lampson key list as marca para que você as substitua.
  • Uma key da API só abre /v1: nunca a interface web, o terminal nem o chat.

Um workspace com keys não é desligado por inatividade: senão, a próxima mensagem do seu bot o encontraria desligado.

Enviar uma mensagem§

curl -X POST https://seu-lampson/w/tienda/v1/messages \
  -H "Authorization: Bearer lk_…" -H "Content-Type: application/json" \
  -d '{"to": "tienda", "thread": "whatsapp:+5491122334455", "text": "vocês têm pão integral?"}'
{"agent": "tienda", "thread": "whatsapp:+5491122334455", "session": "20261016-132332-8546",
 "text": "Olá! Sim, temos pão integral de fermentação natural a $3.200.", "steps": 2,
 "usage": {"input": 1453, "output": 148, "cached": 1024}, "stopped": "done",
 "batch": ["m59429972irl8"], "lead": "m59429972irl8"}

O body é um envelope:

campo
texta mensagem (obrigatório)
too agente (por padrão, o do workspace)
threadquem/o que é esta conversa: mesmo thread = mesma conversa. Cada key tem as suas: outro app com o mesmo thread começa outra
sessionou uma sessão conhecida, desta mesma key (a de outra key dá 404)
images[{"media_type": "image/jpeg", "data": "<base64>"}] — os modelos com visão as veem
from, metalivres: viajam com a mensagem (ids do seu sistema, nome do cliente)
sent_atquando o cliente escreveu (unix): ordena uma rajada que chegou fora de ordem
callbackveja abaixo

Erros: 400 (envelope inválido), 401 (sem key ou key inválida), 403 (agente fora da key, ou callback não permitido), 404 (agente inexistente), 429 (limite).

Três formas de receber a resposta§

  • JSON — POST /v1/messages: o request espera o agente e devolve o resultado.
  • Streaming — POST /v1/messages/stream: Server-Sent Events com cada passo (session, assistant, tool_call…, done), como lampson run --json.
  • Callback — POST /v1/messages com "callback": "https://…": responde 202 {"job": "m…", "status": "queued"} na hora e, quando o agente termina, o Lampson faz um POST para a sua URL. É o que os webhooks do WhatsApp e companhia precisam, porque exigem uma resposta rápida.

O callback leva {job, jobs, batch, status, agent, thread, session, text, steps, usage, stopped, meta}. Ele vai assinado com o segredo da key que o pediu, que o lampson key add mostra uma única vez junto com a key: X-Lampson-Signature: sha256=<HMAC-SHA256 do body>, e X-Lampson-Key diz qual key é. Assim, outro app que use o mesmo Lampson não consegue assinar um callback falso para o seu. As keys criadas antes do Lampson 0.5.1 assinam com LAMPSON_WEBHOOK_SECRET, como antes. Verifique com o SDK ou:

import hmac, hashlib
ok = hmac.compare_digest("sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest(), signature)

GET /v1/jobs/<id> devolve o estado de uma mensagem enviada com callback.

A caixa de entrada§

Cada conversa (agente + thread) tem a sua caixa de entrada. Isso já vem resolvido, não precisa configurar:

  • Nunca dois turnos ao mesmo tempo na mesma conversa. Clientes diferentes rodam, sim, em paralelo.
  • As rajadas se juntam. O turno começa após 3 segundos sem mensagens novas (ou 15 desde a primeira): «oi» / «quanto custa o pão sem glúten?» / «tem em estoque?» vão em um turno e recebem uma resposta — a mesma nos três requests, com batch (as mensagens do lote) e lead (a primeira). Com callback sai um POST por lote.
  • O que chega no meio do turno entra no turno em andamento, antes de o agente responder. Se chega quando o modelo já está escrevendo a resposta, o Lampson a descarta e responde de novo com tudo: nunca sai uma resposta que ignora a última mensagem do cliente.

A espera se ajusta por agente com "buffer": {"quiet_s": 3, "max_s": 15}, ou "buffer": false para responder sem esperar (a fila continua). → Agentes

Objetivos§

Um objetivo é algo que um agente (ou uma equipe) trabalha sozinho até terminar.

curl -X POST https://seu-lampson/w/loja/v1/objectives -H "Authorization: Bearer lk_…" \
  -d '{"agent": "cto", "text": "Adicione filtrar por status, com testes; me peça aprovação antes do merge.", "budget_tokens": 400000}'
POST /v1/objectivescriar: {text, agent? | team?, budget_tokens?, round_seconds?} → 201 com o objetivo
GET /v1/objectivesos que esta key pode ver (os dos seus agentes)
GET /v1/objectives/<id>um: status (active, waiting, done, failed, cancelled, paused), progress (último informe), question e question_kind (question ou approval), result, tasks (o quadro), ledger (o registro), spent
POST /v1/objectives/<id>/replyresponder: {text} a uma pergunta, {approved: true|false, text?} a uma aprovação
POST /v1/objectives/<id>/cancelinterromper

Um objetivo waiting não avança nem gasta até você responder.

Outros endpoints§

GET /v1/agentsos agentes que esta key pode usar
GET /v1/jobs/<id>estado de uma mensagem com callback
POST /v1/mcp · /v1/mcp/streamMCP por HTTP → Lampson como servidor MCP
GET /v1/openapi.jsono OpenAPI 3.1 desta API

OpenAPI§

/v1/openapi.json descreve só a API pública — a interface web, o terminal e os webhooks dos canais não aparecem. Use para gerar um cliente na sua linguagem (openapi-generator para Go, Java, C#, PHP…) ou para testar a API na sua ferramenta favorita. Para JavaScript e Python já existe SDK.

Ver como Markdown