/health
Checagem de liveness. Única rota que não vive sob /v1.
Resposta 200
{ status: "ok", version: "0.1.0" }
$ cat docs/api.md
Referência completa da API HTTP exposta pelo AgentCore: os endpoints próprios do adapter (configuração, sessões, eventos) e os controles exclusivos de cada runtime já implementado (Claude Code, Codex e OpenCode).
# base URL local, definida em src/server.ts
$ curl http://127.0.0.1:3000/health
# todas as rotas abaixo, exceto /health, vivem sob o prefixo /v1
$ curl http://127.0.0.1:3000/v1/sessions
Não existe namespace de URL por provedor (nada de /providers/claude ou
/:provider/...). Toda sessão, independente do runtime, é acessada pelos
mesmos endpoints /v1/sessions/:sessionId/.... A distinção acontece dentro
do handler, olhando o campo runtime da sessão. Rotas que não fazem sentido
para um runtime respondem 400 com uma mensagem explicando a restrição.
Erros seguem sempre o mesmo formato, { "error": "mensagem" }, com o
HTTP status comunicando a categoria:
| Status | Significado |
|---|---|
400 | Body/params inválidos, ou a operação não se aplica ao runtime da sessão |
404 | Sessão, permissão ou histórico não encontrado |
409 | Conflito de estado (sessão ocupada, sem conversa pra ramificar/reverter ainda, etc.) |
502 | Falha ao falar com o provedor (Claude SDK / Codex SDK / servidor OpenCode) |
CORS fica habilitado só fora de produção (NODE_ENV !== "production").
Em produção a API é pensada pra ser consumida localmente, sem navegador cruzando origem.
{
id: string,
runtime: "claude" | "codex" | "opencode",
projectPath: string,
providerSessionId?: string,
status: "ready" | "running" | "waiting_permission"
| "completed" | "cancelled" | "error",
createdAt: Date,
title?: string,
forkedFrom?: string,
forkedFromMessageId?: string,
tag?: string,
permissionMode?: "default" | "acceptEdits" | "bypassPermissions"
| "plan" | "dontAsk" | "auto",
model?: string,
// exclusivos do Claude
claudeDeniedTools?: string[],
claudeEffortLevel?: "low" | "medium" | "high" | "xhigh",
usage?: SessionUsage,
// exclusivos do Codex
codexSandboxMode?: "read-only" | "workspace-write" | "danger-full-access",
codexReasoningEffort?: "minimal" | "low" | "medium" | "high" | "xhigh",
codexWebSearchMode?: "disabled" | "cached" | "live",
codexWebSearchEnabled?: boolean,
codexAdditionalDirectories?: string[],
codexUsage?: CodexSessionUsage,
}
{ type: "agent.started", sessionId }
{ type: "user.message", sessionId, text, messageId?, attachments? }
{ type: "assistant.delta", sessionId, text }
{ type: "assistant.message", sessionId, text, messageId? }
{ type: "tool.started", sessionId, tool, input }
{ type: "tool.completed", sessionId, tool, output? }
{ type: "permission.requested", sessionId, permissionId, tool, description }
{ type: "agent.completed", sessionId }
{ type: "agent.cancelled", sessionId }
{ type: "agent.error", sessionId, message }
{ type: "agent.todo_list", sessionId, items: [{ text, status }] }
// Claude (session.usage)
{ totalCostUsd, inputTokens, outputTokens,
cacheReadInputTokens, cacheCreationInputTokens,
modelUsage: { [model]: { inputTokens, outputTokens,
cacheReadInputTokens, cacheCreationInputTokens, costUsd } } }
// Codex (session.codexUsage)
{ inputTokens, cachedInputTokens, cacheWriteInputTokens,
outputTokens, reasoningOutputTokens }
// OpenCode (consultado ao vivo no servidor OpenCode)
{ costUsd, inputTokens, outputTokens, reasoningTokens,
cacheReadTokens, cacheWriteTokens }
/health
Checagem de liveness. Única rota que não vive sob /v1.
Resposta 200
{ status: "ok", version: "0.1.0" }
/v1/config
Retorna a configuração atual do adapter: quais runtimes estão habilitados.
Resposta 200
{
claude: { enabled: boolean },
codex: { enabled: boolean },
opencode: { enabled: boolean },
}
/v1/config
Habilita/desabilita um ou mais runtimes de uma vez. Persistido em data/config.json.
Body (pelo menos uma chave é obrigatória)
| Campo | Tipo |
|---|---|
| claude | { enabled?: boolean } |
| codex | { enabled?: boolean } |
| opencode | { enabled?: boolean } |
Resposta 200
A configuração completa já atualizada, mesmo formato do GET /v1/config.
/v1/agents
Lista os runtimes habilitados e os modelos que cada um relata como disponível
(consulta ao vivo via listModels() de cada runtime).
Resposta 200
{
agents: [
{ runtime: "claude" | "codex" | "opencode",
models: [{ id: string, displayName: string, description?: string }] }
]
}
Um runtime cuja consulta de modelos falhar é simplesmente omitido da lista (o erro é apenas logado).
Válidos para os três runtimes, salvo indicação contrária em cada rota.
/v1/sessions
Cria um registro de sessão. Não inicia o agente, isso só acontece ao enviar a primeira mensagem.
Body
| Campo | Tipo | Obrigatório |
|---|---|---|
| runtime | "claude" | "codex" | "opencode" | sim |
| projectPath | string | sim |
Resposta 201
Objeto AgentSession.
/v1/sessions
Lista sessões conhecidas, com filtro por status e paginação.
Query params
| Campo | Tipo | Padrão |
|---|---|---|
| status | ready | running | waiting_permission | completed | cancelled | error | (sem filtro) |
| limit | inteiro positivo | 20 |
| offset | inteiro >= 0 | 0 |
Resposta 200
{ sessions: AgentSession[], total: number, limit: number, offset: number }
/v1/sessions/:sessionId
Consulta o estado atual de uma sessão (status, providerSessionId, configurações, uso, etc).
Resposta 200
Objeto AgentSession. 404 se não existir.
/v1/sessions/:sessionId
Renomeia a sessão, alterando apenas o título exibido.
Body
| Campo | Tipo | Obrigatório |
|---|---|---|
| title | string | sim |
Resposta 200
Objeto AgentSession atualizado.
/v1/sessions/:sessionId
Remove o registro local da sessão e, quando o runtime suporta, também a conversa do lado do provedor (Claude e OpenCode; Codex não tem equivalente na SDK).
Resposta 200
{ deleted: true }
409 se a sessão estiver running ou waiting_permission.
/v1/sessions/:sessionId/history
Histórico de mensagens da conversa, normalizado para o formato AgentEvent.
A fonte varia por runtime: log local do Codex, API nativa do OpenCode, ou
getSessionMessages da Claude Agent SDK.
Query params
| Campo | Tipo |
|---|---|
| limit | inteiro positivo |
| offset | inteiro >= 0 |
Resposta 200
{ events: AgentEvent[] }
404 se a sessão nunca chegou a trocar mensagens com o agente.
/v1/sessions/:sessionId/usage
Uso acumulado de tokens/custo da sessão. Formato depende do runtime, veja Modelos de dados.
Resposta 200
session.usage (Claude), session.codexUsage (Codex) ou
consulta ao vivo no servidor OpenCode.
/v1/sessions/:sessionId/fork
Ramifica a conversa em uma nova sessão independente, sem afetar a original.
Body
| Campo | Tipo | Obrigatório |
|---|---|---|
| upToMessageId | string | não (corta a ramificação nessa mensagem) |
Resposta 201
Nova AgentSession, com forkedFrom apontando pra sessão original.
somente claude / opencode
Codex não tem operação de fork na SDK. 409 se a sessão ainda não tem conversa (sem providerSessionId).
/v1/sessions/:sessionId/tag
Define ou limpa uma tag livre na sessão.
Body
| Campo | Tipo | Obrigatório |
|---|---|---|
| tag | string | null | sim (null limpa a tag) |
Resposta 200
Objeto AgentSession atualizado.
Para sessões Claude com conversa já iniciada, a tag também é espelhada do lado do provedor.
/v1/sessions/:sessionId/messages
assíncrono
Envia uma mensagem ao agente. A execução roda em background; a resposta HTTP volta imediatamente e o progresso é acompanhado via SSE. Limite de corpo de 32 MB (por causa dos anexos em base64).
Body
| Campo | Tipo | Obrigatório |
|---|---|---|
| content | string | sim |
| attachments | { kind: "image"|"document", mediaType, data (base64), filename? }[] | não |
Resposta 202
{ accepted: true }
Tipos de mídia aceitos: imagem jpeg, png, gif, webp; documento pdf, text/plain.
Codex só aceita anexos de imagem; OpenCode ainda não suporta anexos. 409 se a sessão já
estiver running ou waiting_permission.
/v1/sessions/:sessionId/events
SSE
Conexão Server-Sent Events com os eventos ao vivo da execução da sessão. Cada
evento chega como event: <type> seguido de data: <AgentEvent em JSON>.
A conexão fica aberta até o cliente desconectar.
Eventos possíveis
Ver union AgentEvent em Modelos de dados.
/v1/sessions/:sessionId/cancel
Cancela a execução em andamento. Apenas sinaliza o cancelamento; o evento agent.cancelled confirma quando de fato parar.
Resposta 200
{ cancelled: true }
409 se a sessão não estiver running.
Mesmo endpoint pros três runtimes, com regras de aplicabilidade próprias em cada um.
/v1/sessions/:sessionId/permission-mode
Define o modo de permissão da sessão, usado como padrão nas próximas execuções.
Body
| Campo | Tipo |
|---|---|
| mode | default | acceptEdits | bypassPermissions | plan | dontAsk | auto |
Resposta 200
{ mode, applied: "live" | "pending" }
applied: "live" quando a sessão já está em execução e o Claude consegue aplicar na hora.
Para o OpenCode só default (agent "build") e plan (agent "plan") são aceitos.
não aplicável ao Codex
/v1/sessions/:sessionId/model
Define o modelo da sessão. null reseta pro padrão da CLI.
Body
| Campo | Tipo |
|---|---|
| model | string | null |
Resposta 200
{ model, applied: "live" | "pending" }
Aplicação ao vivo ("live") só existe hoje para sessões Claude em execução.
/v1/sessions/:sessionId/rewind
Reverte as edições de arquivo feitas a partir de uma mensagem de usuário específica.
Body
| Campo | Tipo | Obrigatório |
|---|---|---|
| userMessageId | string | sim |
| dryRun | boolean | não, só suportado no Claude |
Resposta 200
{ canRewind: boolean, filesChanged?: number,
insertions?: number, deletions?: number, error?: string }
somente claude / opencode
Codex não tem sistema de rewind. 409 se a sessão ainda não tem conversa pra reverter.
/v1/sessions/:sessionId/permissions/:permissionId/approve
Aprova um pedido de permissão de ferramenta pendente (evento permission.requested).
Resposta 200
{ approved: true }
não aplicável ao Codex
404 se o pedido já tiver sido respondido ou nunca existiu.
/v1/sessions/:sessionId/permissions/:permissionId/reject
Rejeita um pedido de permissão pendente.
Body
| Campo | Tipo | Obrigatório |
|---|---|---|
| reason | string | não (padrão: "Rejected by user") |
Resposta 200
{ rejected: true }
não aplicável ao Codex
O OpenCode não aceita um motivo em texto livre; reason é aceito no corpo mas
não é repassado ao servidor OpenCode.
Rotas exclusivas de sessões com runtime: "claude". Respondem 400 para qualquer outro runtime.
/v1/sessions/:sessionId/claude-tools
Lista as tools que a Claude Code CLI reportou disponíveis para o projeto, a partir do cache por projectPath.
Resposta 200
{ tools: string[] | null, updatedAt: string | null }
/v1/sessions/:sessionId/claude-tool-permissions
Configura a lista de tools que o Claude não pode usar nesta sessão.
Body
| Campo | Tipo | Obrigatório |
|---|---|---|
| deny | string[] | sim (nomes livres, sem catálogo fechado) |
Resposta 200
{ deny: string[], applied: "pending" }
/v1/sessions/:sessionId/claude-effort-level
Configura o esforço de raciocínio do modelo Claude para esta sessão.
Body
| Campo | Tipo |
|---|---|
| effort | low | medium | high | xhigh |
Resposta 200
{ effort, applied: "pending" }
Rotas exclusivas de sessões com runtime: "codex". Respondem 400 para qualquer outro runtime.
/v1/sessions/:sessionId/codex-sandbox-mode
Configura o modo de sandbox/permissão de sistema de arquivos do Codex para esta sessão.
Body
| Campo | Tipo |
|---|---|
| mode | read-only | workspace-write | danger-full-access |
Resposta 200
{ mode, applied: "pending" }
/v1/sessions/:sessionId/codex-reasoning-effort
Configura o esforço de raciocínio do modelo Codex para esta sessão.
Body
| Campo | Tipo |
|---|---|
| effort | minimal | low | medium | high | xhigh |
Resposta 200
{ effort, applied: "pending" }
/v1/sessions/:sessionId/codex-web-search
Habilita/configura a busca na web do Codex para esta sessão.
Body (pelo menos um dos dois é obrigatório)
| Campo | Tipo |
|---|---|
| mode | disabled | cached | live |
| enabled | boolean |
Resposta 200
{ mode, enabled, applied: "pending" }
/v1/sessions/:sessionId/codex-additional-directories
Concede ao Codex acesso a diretórios extras fora do projectPath da sessão.
Body
| Campo | Tipo | Obrigatório |
|---|---|---|
| directories | string[] (caminhos absolutos, precisam existir) | sim |
Resposta 200
{ directories: string[], applied: "pending" }
400 se algum caminho não for absoluto ou não existir como diretório.
O OpenCode não tem endpoints exclusivos. Ele é tratado como um branch a mais dentro dos endpoints compartilhados listados em Ciclo de vida, Execução & eventos e Controles compartilhados, com as seguintes particularidades:
| Endpoint | Particularidade no OpenCode |
|---|---|
| history / usage | Consultados ao vivo no servidor OpenCode, sem cache local |
| messages | Não aceita anexos ainda (400 se attachments vier preenchido) |
| permission-mode | Só aceita default (agent "build") ou plan (agent "plan") |
| rewind | Sem modo dryRun, o revert do snapshot é sempre aplicado de verdade |
| permissions/approve & reject | Aceita reason no corpo por consistência, mas o servidor OpenCode só recebe "aprovado" ou "rejeitado" |