Skip to main content

Tickets

Inbox de issues — tickets com status, prioridade e responsável Tickets são threads de conversa duráveis. Diferente de uma sessão de chat — que vive enquanto o terminal está aberto — um ticket sobrevive a restarts, acumula contexto, pode ser pego por qualquer agente e acompanha o progresso por um workflow definido. Use uma sessão para perguntas descartáveis. Use um ticket para qualquer coisa que você queira retomar, repassar a outro agente ou acompanhar até o fim.

Anatomia de um Ticket

Comentários e atividade juntos formam a timeline do ticket — o histórico completo de tudo que aconteceu.

Estados do Workflow

  • open — ninguém pegou ainda
  • in_progress — um agente fez checkout e está trabalhando
  • waiting — bloqueado em input externo (resposta do cliente, decisão humana)
  • resolved — trabalho terminado, aguardando confirmação final
  • closed — terminal; é o que um soft-delete vira
O backend grava resolved_at automaticamente quando o status vira resolved ou closed.

Criando um Ticket

Via skill create-ticket

No Claude Code:
“Abra um ticket para o Hawk sobre o webhook do Stripe retornando 500.”
A skill pergunta título, descrição, prioridade, assignee/project/goal opcionais e chama POST /api/tickets.

Via dashboard

A página Tickets tem um formulário “Novo Ticket”.

Via API

Checkout Atômico

A feature de segurança central. Quando um agente quer trabalhar em um ticket, ele chama:
O backend executa:
Exatamente um agente ganha o lock. Todos os outros recebem HTTP 409 already_locked com o nome do detentor atual. É isso que torna tickets seguros quando múltiplos heartbeats apontam para a mesma fila — só um agente consegue trabalhar no ticket por vez.

Release

Apenas o detentor do lock pode liberar. O backend verifica locked_by == agent antes de limpar o lock.

Limpeza de locks parados

ticket_janitor.py roda periodicamente e libera qualquer lock mais antigo que seu lock_timeout_seconds. Isso evita que um agente que crashou segure um ticket para sempre.

Comentários e Mentions

Comentários são a conversa viva. A descrição é estática; os comentários se acumulam.

@Mentions disparam triggers de heartbeat

Se o comentário contém @agent-slug e esse agente tem um heartbeat habilitado com mention em seus wake_triggers, o backend insere uma linha em heartbeat_triggers. O dispatcher pega no próximo tick e acorda o agente — com o ticket + comentário como contexto. É assim que você passa trabalho a um agente proativo sem precisar acionar um humano antes.

Storm guard

Máximo de 3 mentions por comentário. Os extras são silenciosamente descartados. Isso evita que alguém (humano ou agente) acidentalmente dispare 50 heartbeats numa mensagem só.

Tickets vs Sessões

Se você quer fazer uma pergunta rápida e seguir adiante — sessão. Se o resultado importa, múltiplos agentes podem mexer ou você quer um registro — ticket.

Auto-binding de sessão

Quando um agente cria um ticket dentro de uma sessão de chat, o terminal-server detecta a resposta da API e amarra a sessão ao ticket automaticamente. O sidebar da sessão mostra um chip #xxxxxxxx para você ver de relance qual ticket cada conversa cobre. Chat com badge de ticket no sidebar Sessões também podem ser anexadas manualmente a um ticket existente via dropdown “No ticket” acima do input de mensagem.

Autocomplete de slash-commands

Digitar / no chat abre um popup com todas as skills disponíveis — filtre por substring, navegue com ↑↓, insira com Enter/Tab, feche com Esc. Autocomplete de slash-commands no chat

Operando em Tickets

Detalhe do ticket — header, timeline, comentários

Listar / filtrar

Atualizar

Campos permitidos: status, priority, assignee_agent, title, description, project_id, goal_id. Toda mudança é registrada no activity log.

Timeline

Retorna comentários + atividade, mesclados e ordenados cronologicamente.

Ações em lote

Suportadas: close, reassign, relink_goal.

Close vs delete

  • DELETE /api/tickets/{id} (padrão, soft) — vira o status para closed, mantém o ticket e o histórico
  • DELETE /api/tickets/{id}?hard=true (apenas admin) — remove a linha do ticket completamente
Prefira soft. Histórico importa quando você volta a um problema parecido seis meses depois.

Exportar

Mesmos filtros do list. Até 10.000 linhas por exportação.

Anti-padrões

  • Pular o checkout num agente automatizado. Dois heartbeats disparam no mesmo segundo, ambos pegam o mesmo ticket, ambos rodam — o estado corrompe. Sempre faça checkout.
  • Escrever tickets só com descrição para trabalho em andamento. A descrição é estática. Updates ao vivo vão em comentários, para que a timeline conte a história.
  • Mencionar agentes sem heartbeat habilitado. A mention não dispara nada. Se você precisa que aquele agente pegue o trabalho, habilite o heartbeat dele primeiro.
  • Usar ?hard=true casualmente. Você perde o histórico. Se precisa que o ticket suma mas ainda seja revisável, faça soft-close e arquive.
  • Inflação de prioridade. Se tudo é urgent, nada é. Reserve urgent para outages e issues P1 de cliente.

Skills do CLI

Relacionados

  • docs/heartbeats.md — @mentions em comentários de ticket acordam heartbeats
  • docs/goals.md — ligar tickets a goals para acompanhamento de progresso
  • Código: dashboard/backend/routes/tickets.py, dashboard/backend/ticket_janitor.py, dashboard/backend/ticket_inbox.py