Como escrever specs de agentes de IA que rodam no nosso apps/agno e expor os endpoints (agno + espelho no backend Node). Fiel ao código atual.
arquivo:linha, template e exemplo) vive versionada em specs/Yousa Agno/Conhecimento e Memoria/Tarefas/24-guia-agentes-ia-agno/: guia-agentes-agno.md, template-spec-agente.md, exemplo-doc-feedback-app.md. O passo a passo oficial de registrar um agente de manifesto é o apps/agno/REGISTERING-AN-AGENT.md.Crie um agente quando a tarefa exige decisão ou linguagem natural que depende de um LLM: classificar, resumir, redigir, conversar, validar conteúdo, extrair dados de texto livre.
Se a tarefa é determinística (mover status, calcular prazo, disparar webhook), não é agente — é automação comum no backend. Todo agente é advisory: sugere, o advogado decide.
| A — Manifesto (agno Agent) | B — Endpoint FastAPI | |
|---|---|---|
| Declaração | AgentManifest em manifests.py | pasta minha_feature/route.py + register(app) |
| LLM | agno Agent com OpenRouter(id=model) | OpenAI SDK apontada ao OpenRouter direto |
| Prompt | seed no código → versão ativa no banco (Sandbox) | constante _SYSTEM_BASE no módulo |
| I/O | conversacional (chat / test-run) | contrato JSON próprio (você define) |
| Sandbox | sim (registry) | não (a menos que também tenha manifesto) |
| Use quando | conversacional geral, prompt governado | I/O estruturado, pipeline, dry-run, JSON estrito |
Regra prática: agente de documentos / triagem / agendamento → estilo B. Chat do caso / assistente → estilo A. Pode combinar.
Referência: apps/agno/pre_kickoff/route.py. Ordem do route.py:
_SYSTEM_BASE — a constante do promptRequest(BaseModel) — Pydantic do request_verify_bearer(request) — auth por AGNO_API_KEY_build_system(...) — monta o system prompt com contexto do caso_complete(...) — a única função que fala com o LLM (é o que os testes mockam)register(app) — declara o @app.post("/minha-feature/...")Wire final em apps/agno/app.py: import minha_feature.route as mf e mf.register(app).
Pipeline rico (ferramentas externas, dry-run, RAG, persistência): siga apps/agno/intake/ (route → pipeline → llm → schema → data → rag).
manifests.py após o seed não muda produção — muda via Sandbox (novo draft → ativar). Procedimento completo: apps/agno/REGISTERING-AN-AGENT.md.case_id (int) é a chave para agentes que atuam sobre um caso.AGNO_API_KEY (helper _verify_bearer; no-op se a env não estiver setada).Exemplo real: POST /pre-kickoff/draft-message in {case_id, client_name?, case_type?} → out {message}.
Escrita (intake/rag.py): embeddings text-embedding-3-small (1536 dims), upsert idempotente por (case_id, source_type) em case_knowledge_chunks.
Leitura: injeta os últimos N chunks no system prompt. O source_type é o que a Base de conhecimento do Caso (aba Geral) agrupa e mostra ao time — escolha um claro.
O frontend nunca fala com o agno direto: passa pelo apps/backend. Padrão:
requireIdentity (JWT do caller); escrita/sandbox também com requireCoordinator.createXHandler({ supabase, agnoBaseUrl, agnoToken, fetch }).fetch no agno com Bearer → 502 em falha.case_agent_messages). Mount em server.mjs.Convenção atual: novos routers em apps/backend/src/routes/ (ex.: agents-pre-kickoff.mjs).
apps/agno/tests/ com pytest: cria FastAPI() isolado, chama register(app), TestClient, e patch("...route._complete", return_value=...) para o LLM nunca rodar.
Obrigatório: teste de contrato (mockando _complete) + teste de não-vazamento de PII em log. No espelho Node, testar a factory com fetch fake.
agno: DATABASE_URL, OPENROUTER_API_KEY, AGNO_DEFAULT_MODEL, AGNO_API_KEY, CORS_ALLOWED_ORIGINS, PORT (8000).
backend Node: AGNO_BASE_URL / AGNO_URL (default http://localhost:8000).
talks_to_client=true, PT-BR claro.manifests.py/intake/llm.py usam anthropic/claude-sonnet-4.6; intake/chat.py e pre_kickoff/route.py hardcodam -4-6. Canônico: ler de AGNO_DEFAULT_MODEL, não hardcodar.AGNO_BASE_URL vs AGNO_URL: feature routes usam um, a sandbox usa outro. Canônico: padronizar num nome (decisão do time).
template-spec-agente.md: objetivo, contrato JSON, scoping, prompt-seed, RAG source_type, espelho Node, testes, env, compliance.minha_feature/route.py e dar register(app) no app.py. Estilo A: AgentManifest em manifests.py + seguir REGISTERING-AN-AGENT.md.source_type e garantir só-resumo idempotente.createXHandler + requireIdentity + mount em server.mjs._complete + PII-em-log.OPENROUTER_API_KEY, AGNO_API_KEY, AGNO_BASE_URL, DATABASE_URL.Quando um documento chega pelo APP, o agente revisa e gera o feedback estruturado. Consumidor visível: document.html.
POST /documents/review
in: { case_id, document_id, document_type_expected?, file_ref }
out: { verdict: "ok"|"ressalva"|"rejeitado",
checks: [ { name, pass, note } ],
summary, attorney_review_required: true, disclaimer }
Checks v1: tipo confere · legível · completo · assinado/datado. O summary vira o card "Doc feedback APP"; o verdict dirige o stepper.
RAG: indexa só o summary com source_type='document_review'.
Fora do escopo v1 (vira tarefa futura): OCR/leitura do arquivo, classificação multi-tipo, extração de campos. Detalhe completo em specs/Yousa Agno/Conhecimento e Memoria/Tarefas/24-guia-agentes-ia-agno/exemplo-doc-feedback-app.md.