mirror of
https://github.com/hoshikawa2/agent_platform_oci.git
synced 2026-07-09 22:04:21 +00:00
First commit
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# Atualização do Template Backend — Analytics, Observer, NOC/GRL e OutputSupervisor
|
||||
|
||||
Esta versão do `agent_template_backend` foi atualizada para consumir as novidades transportadas para o `agent_framework`.
|
||||
|
||||
## 1. Analytics e Pub/Sub
|
||||
|
||||
O backend não chama mais diretamente apenas o publisher antigo de eventos. Agora ele cria um `AnalyticsPublisher`:
|
||||
|
||||
```python
|
||||
from agent_framework.analytics.factory import create_analytics_publisher
|
||||
from agent_framework.observability.observer import AgentObserver
|
||||
|
||||
analytics = create_analytics_publisher(settings)
|
||||
observer = AgentObserver(analytics=analytics)
|
||||
```
|
||||
|
||||
Com isso, o mesmo backend pode publicar em:
|
||||
|
||||
- OCI Streaming
|
||||
- GCP Pub/Sub
|
||||
- CompositePublisher, quando `ANALYTICS_PROVIDERS=oci_streaming,pubsub`
|
||||
- Noop, quando analytics estiver desligado
|
||||
|
||||
## 2. Configuração mínima
|
||||
|
||||
```env
|
||||
ENABLE_ANALYTICS=true
|
||||
ANALYTICS_PROVIDERS=pubsub
|
||||
GCP_PUBSUB_TOPIC_PATH=projects/<project-id>/topics/<topic-name>
|
||||
GOOGLE_APPLICATION_CREDENTIALS=/secrets/gcp-service-account.json
|
||||
```
|
||||
|
||||
Para publicar simultaneamente em OCI Streaming e GCP Pub/Sub:
|
||||
|
||||
```env
|
||||
ENABLE_ANALYTICS=true
|
||||
ANALYTICS_PROVIDERS=oci_streaming,pubsub
|
||||
ENABLE_OCI_STREAMING=true
|
||||
OCI_STREAM_ENDPOINT=<endpoint>
|
||||
OCI_STREAM_OCID=<stream-ocid>
|
||||
GCP_PUBSUB_TOPIC_PATH=projects/<project-id>/topics/<topic-name>
|
||||
```
|
||||
|
||||
## 3. Observer corporativo
|
||||
|
||||
O workflow recebeu emissão automática dos principais eventos corporativos:
|
||||
|
||||
- `NOC.001`: início do workflow
|
||||
- `NOC.005`: exceção fatal no workflow
|
||||
- `NOC.006`: fim do workflow antes da resposta final
|
||||
- `IC.AGENT_COMPLETED`: evento informacional de conclusão
|
||||
- `GRL.001` a `GRL.009`: emitidos pelo `OutputSupervisor`
|
||||
|
||||
## 4. OutputSupervisor
|
||||
|
||||
Foi inserido um novo nó LangGraph:
|
||||
|
||||
```text
|
||||
agent -> output_supervisor -> output_guardrails -> judge -> supervisor_review -> persist
|
||||
```
|
||||
|
||||
O `OutputSupervisor` não substitui o supervisor de roteamento. Ele valida a saída candidata do agente usando o contrato corporativo:
|
||||
|
||||
- `allow`
|
||||
- `sanitize`
|
||||
- `retry`
|
||||
- `block`
|
||||
- `handover`
|
||||
- `observe`
|
||||
|
||||
Para compatibilidade com os guardrails já existentes, o template inclui o adapter `LegacyOutputGuardrailRail`, que converte decisões antigas `allowed=True/False` para `RailAction`.
|
||||
|
||||
## 5. Campos adicionados ao AgentState
|
||||
|
||||
```python
|
||||
supervisor_action: str
|
||||
supervisor_guidance: str
|
||||
supervisor_attempt: int
|
||||
supervisor_handover_reason: str
|
||||
output_supervisor_results: list[dict]
|
||||
output_guardrails_already_applied: bool
|
||||
```
|
||||
|
||||
## 6. Arquivos alterados
|
||||
|
||||
- `agent_template_backend/app/main.py`
|
||||
- `agent_template_backend/app/workflows/agent_graph.py`
|
||||
- `agent_template_backend/app/state.py`
|
||||
- `agent_template_backend/.env`
|
||||
- `agent_template_backend/requirements.txt`
|
||||
- `agent_framework/src/agent_framework/config/settings.py`
|
||||
|
||||
## 7. Observação importante
|
||||
|
||||
O `OutputSupervisor` roda os guardrails de saída por meio do adapter legado e marca `output_guardrails_already_applied=True`. Assim o nó `output_guardrails` permanece no grafo para compatibilidade, mas evita reexecutar a mesma validação quando o supervisor já aplicou os rails.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Backends atualizados para ConversationSummaryMemory
|
||||
|
||||
Esta versão dos backends foi compatibilizada com a versão do framework que adiciona `ConversationSummaryMemory`.
|
||||
|
||||
## O que mudou
|
||||
|
||||
- `app/main.py` agora inicializa `create_conversation_summary_memory(...)` junto com `create_memory(...)`.
|
||||
- `AgentWorkflow` recebe `summary_memory` e repassa para os agentes.
|
||||
- Os agentes não montam mais prompts manuais para o LLM; agora usam `build_messages()` do framework.
|
||||
- Antes da chamada ao LLM, os agentes executam `await self.prepare_memory_context(state)`.
|
||||
- Quando habilitado por `.env`, o prompt passa a receber:
|
||||
- resumo acumulado da conversa;
|
||||
- últimas mensagens completas;
|
||||
- mensagem atual;
|
||||
- BusinessContext;
|
||||
- MCP results;
|
||||
- RAG context e metadata.
|
||||
|
||||
## Configuração
|
||||
|
||||
```env
|
||||
ENABLE_CONVERSATION_SUMMARY_MEMORY=true
|
||||
MEMORY_CONTEXT_STRATEGY=summary
|
||||
MEMORY_HISTORY_LIMIT=80
|
||||
MEMORY_RECENT_MESSAGES_LIMIT=8
|
||||
MEMORY_SUMMARY_TRIGGER_MESSAGES=20
|
||||
MEMORY_MAX_SUMMARY_CHARS=6000
|
||||
MEMORY_SUMMARY_USE_LLM=true
|
||||
MEMORY_INJECT_RECENT_MESSAGES=true
|
||||
MEMORY_INJECT_SUMMARY=true
|
||||
```
|
||||
|
||||
## Backends alterados
|
||||
|
||||
- `backoffice_convertido_framework`
|
||||
- `agent_template_backend`
|
||||
- `agent_template_backend_day_zero`
|
||||
|
||||
## Observação importante
|
||||
|
||||
Estes backends esperam que o pacote `agent_framework` instalado/conectado seja a versão com os módulos:
|
||||
|
||||
- `agent_framework.memory.summary_memory`
|
||||
- `agent_framework.memory.summary_store`
|
||||
- `AgentRuntimeMixin.prepare_memory_context()`
|
||||
- `AgentRuntimeMixin.build_messages()` com injeção de memória
|
||||
|
||||
Use junto com o ZIP `agent_framework_conversation_summary_memory.zip`.
|
||||
60
templates/backend_day_zero/docs/DAY_ZERO_COMO_USAR.md
Normal file
60
templates/backend_day_zero/docs/DAY_ZERO_COMO_USAR.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Como usar o `agent_template_backend_day_zero`
|
||||
|
||||
Este template é uma cópia do backend completo, mas com a lógica dos agentes de exemplo comentada.
|
||||
|
||||
## Fluxo mantido
|
||||
|
||||
```text
|
||||
Gateway / Canal
|
||||
-> AgentWorkflow
|
||||
-> Input Guardrails
|
||||
-> Router / Supervisor Router
|
||||
-> Agente
|
||||
-> OutputSupervisor
|
||||
-> Output Guardrails
|
||||
-> Judges
|
||||
-> Persistência
|
||||
```
|
||||
|
||||
## Onde escrever código
|
||||
|
||||
O ponto principal é o método `run()` dos agentes em `app/agents/`.
|
||||
|
||||
A estrutura esperada pelo workflow é:
|
||||
|
||||
```python
|
||||
async def run(self, state):
|
||||
...
|
||||
return {
|
||||
"answer": answer,
|
||||
"next_state": "MEU_ESTADO"
|
||||
}
|
||||
```
|
||||
|
||||
## Como usar MCP
|
||||
|
||||
Dentro de `run()`:
|
||||
|
||||
```python
|
||||
tool_context = await self._collect_tool_context(state)
|
||||
```
|
||||
|
||||
## Como usar RAG
|
||||
|
||||
Dentro de `run()`:
|
||||
|
||||
```python
|
||||
rag_context, rag_metadata = await self._retrieve_rag_context(state)
|
||||
```
|
||||
|
||||
## Como chamar o LLM com cache/telemetria
|
||||
|
||||
```python
|
||||
answer = await self._invoke_llm_cached(state, "MeuAgente", messages)
|
||||
```
|
||||
|
||||
## Como ajustar roteamento
|
||||
|
||||
Edite `config/routing.yaml`.
|
||||
|
||||
O arquivo original foi mantido para servir de referência, mas as intents devem ser adaptadas para o domínio do novo agente.
|
||||
@@ -0,0 +1,84 @@
|
||||
# FRAMEWORK_CHANNEL_INPUT_MODE
|
||||
|
||||
This backend setting controls what kind of channel input the Agent Framework backend accepts.
|
||||
|
||||
It replaces the ambiguous use of `CHANNEL_GATEWAY_MODE` inside the backend.
|
||||
|
||||
## Values
|
||||
|
||||
```env
|
||||
FRAMEWORK_CHANNEL_INPUT_MODE=embedded
|
||||
```
|
||||
|
||||
The backend may use internal channel adapters to interpret simple/native channel payloads. This is useful for demos, labs, local frontend, curl tests, and simple environments.
|
||||
|
||||
```env
|
||||
FRAMEWORK_CHANNEL_INPUT_MODE=external
|
||||
```
|
||||
|
||||
The backend accepts only a normalized `GatewayRequest` produced by an external Channel Gateway. It does not parse native WhatsApp, Voice, Teams, or other channel payloads.
|
||||
|
||||
## Recommended enterprise setup
|
||||
|
||||
In the external channel gateway service:
|
||||
|
||||
```env
|
||||
CHANNEL_GATEWAY_RUNTIME_MODE=adapter
|
||||
```
|
||||
|
||||
In this backend:
|
||||
|
||||
```env
|
||||
FRAMEWORK_CHANNEL_INPUT_MODE=external
|
||||
```
|
||||
|
||||
Flow:
|
||||
|
||||
```text
|
||||
External channel / browser / customer adapter
|
||||
↓
|
||||
channel_gateway:7000
|
||||
CHANNEL_GATEWAY_RUNTIME_MODE=adapter
|
||||
↓ GatewayRequest
|
||||
agent_template_backend:8000
|
||||
FRAMEWORK_CHANNEL_INPUT_MODE=external
|
||||
↓
|
||||
LangGraph / Agents / MCP / Guardrails
|
||||
```
|
||||
|
||||
## Valid direct request to backend in external mode
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:8000/gateway/message" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"channel": "web",
|
||||
"tenant_id": "default",
|
||||
"agent_id": "telecom_contas",
|
||||
"payload": {
|
||||
"message": "Quero consultar minha fatura",
|
||||
"session_id": "backend-external-ok-001"
|
||||
}
|
||||
}' | jq
|
||||
```
|
||||
|
||||
## Invalid direct request to backend in external mode
|
||||
|
||||
```bash
|
||||
curl -i -s -X POST "http://localhost:8000/gateway/message" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"message": "Quero consultar minha fatura",
|
||||
"session_id": "raw-payload-error-001"
|
||||
}'
|
||||
```
|
||||
|
||||
Expected result: HTTP 422.
|
||||
|
||||
## Legacy compatibility
|
||||
|
||||
`CHANNEL_GATEWAY_MODE` is still present as a legacy alias for older environments, but new deployments should use:
|
||||
|
||||
```env
|
||||
FRAMEWORK_CHANNEL_INPUT_MODE=embedded|external
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
# Langfuse single trace observer fix
|
||||
|
||||
This backend now uses `TelemetryBackedAgentObserver` instead of publishing IC/NOC/GRL through `AgentObserver(analytics=...)`.
|
||||
|
||||
Why: when analytics includes the Langfuse provider, observer events such as `IC.AGENT_COMPLETED` and `NOC.006` may create a second root trace with little detail. Emitting those events through `Telemetry.event(...)` keeps them inside the active request/workflow trace.
|
||||
Reference in New Issue
Block a user