10 KiB
Projeto Agent Framework FIRST-ready
Esta versão mantém a arquitetura do meu_projeto_agent_framework e adiciona os padrões operacionais encontrados no projeto FIRST.
Recursos adicionados
-
SSE no padrão FIRST
GET /gateway/events/{session_id}para streamtext/event-stream.POST /gateway/message/ssepara processar mensagem emitindo eventos SSE.- Eventos:
connected,flow.start,session.upserted,message.received,workflow.started,workflow.completed,message.responded,flow.end. - Keepalive configurável por
SSE_KEEPALIVE_SECONDS. - Lock por sessão para evitar concorrência dentro da mesma conversa.
- Replay de eventos via
Last-Event-IDou query paramlast_event_id.
-
Persistência de sessão e mensagens
- Implementado provider
sqlite, executável localmente. SESSION_REPOSITORY_PROVIDER=sqlite.MEMORY_REPOSITORY_PROVIDER=sqlite.- Tabelas locais:
agent_sessions,agent_messages. - Idempotência por
message_id.
- Implementado provider
-
Checkpoint persistente
- Implementado provider
sqlitepara checkpoint final do workflow. CHECKPOINT_REPOSITORY_PROVIDER=sqlite.- Endpoint de leitura:
GET /sessions/{session_id}/checkpoint.
- Implementado provider
-
Histórico de mensagens
- Endpoint:
GET /sessions/{session_id}/messages. - Histórico usado como memória conversacional antes de chamar o LangGraph.
- Endpoint:
-
Cache
- Novo módulo
agent_framework.cache.cache. - Suporta cache local em memória e Redis se
ENABLE_REDIS_CACHE=true.
- Novo módulo
-
RAG / Vector Store
agent_framework.rag.vector_storeagora possuiInMemoryVectorStore,SQLiteVectorStoree contratoAutonomousVectorStore.- A versão SQLite usa busca lexical local para desenvolvimento.
- O contrato permite trocar por Oracle Vector Search sem alterar a camada de aplicação.
-
Observabilidade
- Mantém Langfuse existente.
- Acrescenta eventos de gateway/SSE/workflow com
session_id,agent_id,tenant_id,message_id, rota e intenção.
Arquitetura resultante
Browser
|-- POST /gateway/message/sse
|-- GET /gateway/events/{session_id}
|
FastAPI Template Backend
|
ChannelGateway
|
SessionRepository + MessageHistory + CheckpointRepository
|
LangGraph AgentWorkflow
|
Guardrails -> Router/Supervisor -> Agent -> Output Guardrails -> Judges
|
Telemetry / Langfuse / OCI Streaming
Como rodar localmente
cd agent_template_backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install -e ../agent_framework
uvicorn app.main:app --host 0.0.0.0 --port 8000
Frontend:
cd agent_frontend
python -m http.server 3000
Abra:
http://localhost:3000
Variáveis principais
SESSION_REPOSITORY_PROVIDER=sqlite
MEMORY_REPOSITORY_PROVIDER=sqlite
CHECKPOINT_REPOSITORY_PROVIDER=sqlite
VECTOR_STORE_PROVIDER=sqlite
SQLITE_DB_PATH=./data/agent_framework.db
ENABLE_SSE=true
SSE_KEEPALIVE_SECONDS=15
ENABLE_MESSAGE_IDEMPOTENCY=true
Teste via curl
Mensagem normal:
curl -X POST http://localhost:8000/gateway/message \
-H 'Content-Type: application/json' \
-d '{"channel":"web","payload":{"text":"teste","message":"teste","session_id":"s1","user_id":"u1","message_id":"m1"}}'
Mensagem com SSE:
curl -N http://localhost:8000/gateway/events/s1
Em outro terminal:
curl -X POST http://localhost:8000/gateway/message/sse \
-H 'Content-Type: application/json' \
-d '{"channel":"web","payload":{"text":"teste","message":"teste","session_id":"s1","user_id":"u1","message_id":"m2"}}'
Histórico:
curl http://localhost:8000/sessions/s1/messages
Checkpoint:
curl http://localhost:8000/sessions/s1/checkpoint
Observação importante
A versão adicionada é executável localmente com SQLite. As classes AutonomousSessionRepository, DatabaseMessageHistory, AutonomousCheckpointRepository e AutonomousVectorStore mantêm o contrato para Oracle Autonomous Database, mas nesta entrega usam SQLite como backend local para permitir rodar e testar sem infraestrutura Oracle.
Evolução de Observabilidade no padrão FIRST
Esta versão adiciona uma camada corporativa de observabilidade ao framework, mantendo os componentes reutilizáveis dentro de agent_framework.
Componentes adicionados
agent_framework/observability/
├── context.py # ContextVar: request_id, session_id, user_id, tenant_id, agent_id, channel, ura_call_id, workflow_id, message_id
├── telemetry.py # Facade central: span, event, generation, rag_event, cache_event, checkpoint_event
├── event_bus.py # Event bus interno para plugar logs, SSE, OCI Streaming, Elastic, Phoenix etc.
├── otel.py # OpenTelemetry opcional via OTLP
├── workflow_events.py # workflow.started, node.started, node.completed, edge.selected, workflow.failed
├── guardrail_events.py # guardrail.<CODE>.evaluated e guardrail.<CODE>.blocked
├── judge_events.py # judge.<NAME>.evaluated
├── streaming_events.py # sse.connected, sse.keepalive, sse.event.emitted
└── decorators.py # decorator @traced para classes do framework
Correlação ponta-a-ponta
Cada chamada HTTP cria ou propaga x-request-id e o fluxo de mensagem vincula:
request_id → tenant_id → agent_id → session_id → user_id → channel → message_id → workflow_id
O contexto usa ContextVar, portanto funciona em chamadas assíncronas, FastAPI, LangGraph e providers LLM.
Langfuse
Ative no .env:
ENABLE_LANGFUSE=true
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_HOST=http://localhost:3000
O framework registra:
Trace de conversa
├── http.request
├── agent.gateway_message
├── workflow.langgraph.ainvoke
├── workflow.input_guardrails
│ └── guardrail.<CODE>.evaluated / blocked
├── workflow.routing_decision
├── workflow.agent.<agent>
│ └── generation.<model>
├── workflow.output_guardrails
├── workflow.judge
│ └── judge.<NAME>.evaluated
├── workflow.supervisor_review
├── workflow.persist
└── sse.event.emitted / sse.keepalive
OpenTelemetry
Ative no .env:
ENABLE_OTEL=true
OTEL_SERVICE_NAME=agent-framework-template
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318/v1/traces
Com isso, os mesmos spans são exportados via OTLP para Elastic, Grafana Tempo, Jaeger, Collector ou outro backend compatível.
SSE observável
O SSEHub agora registra eventos de:
- conexão aberta;
- replay de eventos;
- evento emitido;
- keepalive;
- lock por sessão no processamento de mensagem.
Guardrails e Judges
Além dos eventos agregados (guardrails.input.completed, judges.completed), cada decisão individual gera telemetria própria:
guardrail.MSK.evaluated
guardrail.OOS.blocked
judge.response_quality.evaluated
judge.groundedness.evaluated
Extensão para outros backends
A classe Telemetry.event_bus permite plugar novos handlers sem alterar o workflow. Exemplo:
async def enviar_para_elastic(event):
...
telemetry.event_bus.subscribe(enviar_para_elastic)
Evolução FIRST Enterprise Completa
Esta versão recebeu os componentes que faltavam para aproximar o framework do padrão operacional do projeto FIRST:
Persistência Oracle Autonomous Database
Foram adicionados providers reais Oracle:
OracleSessionRepositoryOracleMessageHistoryOracleCheckpointRepositoryOracleCacheOracleVectorStoreOracleGraphStoreOracleStore
Tabelas criadas automaticamente com prefixo configurável ADB_TABLE_PREFIX:
<PREFIX>_AGENT_SESSION<PREFIX>_AGENT_MESSAGE<PREFIX>_WORKFLOW_CHECKPOINT<PREFIX>_WORKFLOW_CHECKPOINT_WRITE<PREFIX>_WORKFLOW_CHECKPOINT_BLOB<PREFIX>_SSE_EVENT<PREFIX>_CACHE_ENTRY<PREFIX>_RAG_DOCUMENT<PREFIX>_GRAPH_EDGE
Configuração Oracle
SESSION_REPOSITORY_PROVIDER=oracle
MEMORY_REPOSITORY_PROVIDER=oracle
CHECKPOINT_REPOSITORY_PROVIDER=oracle
CACHE_BACKEND_PROVIDER=oracle
VECTOR_STORE_PROVIDER=oracle
GRAPH_STORE_PROVIDER=oracle
SSE_STORE_PROVIDER=oracle
ADB_USER=ADMIN
ADB_PASSWORD=***
ADB_DSN=meu_adb_high
ADB_WALLET_LOCATION=/path/wallet
ADB_WALLET_PASSWORD=***
ADB_TABLE_PREFIX=AGENTFW
SSE Enterprise
O SSE agora possui:
- lock por sessão (
SessionLockManager) - keepalive configurável
- replay por
Last-Event-ID - persistência de eventos em SQLite ou Oracle
- telemetria de conexão, replay, keepalive e desconexão
Endpoint:
GET /gateway/events/{session_id}?last_event_id=123
LangGraph Deep Telemetry
Foi adicionado LangGraphDeepTelemetry com eventos:
langgraph.node.startedlanggraph.node.completedlanggraph.node.failedlanggraph.edge.selected
Esses eventos são enviados para o Event Bus, Langfuse e OpenTelemetry quando habilitados.
Token e Cost Accounting
Foi adicionado:
TokenUsageCollectorCostTracker- cálculo de
prompt_tokens,completion_tokens,cached_tokens,total_tokens - cálculo de
cost_usdecost_brl
Configuração opcional:
USD_BRL_RATE=5.0
MODEL_PRICES_JSON={"openai.gpt-4.1":{"input_per_1m":"2.00","output_per_1m":"8.00"}}
Cache Enterprise
O cache agora é em cascata:
L1: InMemory
L2: Redis, SQLite ou Oracle
Configuração:
ENABLE_REDIS_CACHE=true
REDIS_URL=redis://localhost:6379/0
ou:
CACHE_BACKEND_PROVIDER=oracle
RAG Oracle 23ai
Foi adicionado OracleVectorStore, com suporte a coluna VECTOR e VECTOR_DISTANCE() quando um embedding provider for conectado.
Sem embedding provider, mantém fallback lexical para desenvolvimento local.
Também foi adicionado OracleGraphStore com tabela de arestas, pronto para evoluir para PGQL/Property Graph.
Langfuse
Cada chamada LLM agora gera generation com:
- input
- output
- model
- provider
- token usage
- cost metadata
Além disso, spans de workflow, guardrails, judges, RAG, cache, checkpoint, SSE e LangGraph são publicados pelo mesmo Event Bus.