adjustments: manual v4

This commit is contained in:
2026-09-13 08:52:57 -03:00
parent e16d19083d
commit 4712bcc0dc
12 changed files with 374 additions and 48 deletions

View File

@@ -141,41 +141,65 @@ Recomendações de melhores práticas de segurança da Oracle Cloud Infrastructu
## 1. Visão geral da arquitetura ## 1. Visão geral da arquitetura
O template separa o que é genérico do que é específico. O `agent_template_backend` mantém no `agent_framework_oci` os motores e serviços reutilizáveis da plataforma e implementa localmente apenas a composição, configuração e extensões específicas do agente/domínio. O template é, portanto, uma **composição de referência das capacidades do framework**, e não uma duplicação do core.
A estrutura atual do template é:
```text ```text
agent_template_backend/ agent_template_backend/
├── app/ ├── app/
│ ├── main.py # API FastAPI, gateway, sessão, SSE e entrada do workflow │ ├── main.py # FastAPI, lifecycle, gateway, sessões, SSE, health/readiness e workflows
│ ├── state.py # Contrato de estado compartilhado do LangGraph │ ├── state.py # Contrato de estado compartilhado pelo LangGraph
│ ├── workflows/ │ ├── mcp_gateway_client_factory.py # Criação/configuração do cliente para o MCP Gateway
│ │ └── agent_graph.py # Workflow corporativo com router, guardrails, agentes, judges e persistência
│ ├── agents/ │ ├── agents/
│ │ ├── runtime.py # Recursos comuns para agentes: MCP, RAG, cache, IC, LLM │ │ ├── runtime.py # Runtime comum: LLM, MCP, RAG, memória, cache e recursos do framework
│ │ ├── billing_agent.py # Exemplo de agente de faturas │ │ ├── prompting.py # Composição e aplicação de prompts/profiles por agente
│ │ ├── product_agent.py # Exemplo de agente de produtos │ │ ├── billing_agent.py # Agente de exemplo para faturamento
│ │ ├── orders_agent.py # Exemplo de agente de pedidos │ │ ├── product_agent.py # Agente de exemplo para produtos
│ │ └── support_agent.py # Exemplo de agente de suporte │ │ ├── orders_agent.py # Agente de exemplo para pedidos
│ │ ├── support_agent.py # Agente de exemplo para suporte
│ │ └── README.md # Orientações específicas para implementação de agentes
│ ├── workflows/
│ │ └── agent_graph.py # Composição LangGraph: routing, guardrails, agentes, judges e persistência
│ ├── workflow_actions/
│ │ └── devolucao.py # Exemplo de ação de workflow determinístico/transacional
│ ├── observability/
│ │ └── telemetry_observer.py # Integração de telemetria/observer do template
│ ├── presentation/
│ │ └── tool_renderers.py # Renderização/apresentação de resultados de tools
│ └── examples/ # Exemplos de IC, NOC, GRL, MCP e observer │ └── examples/ # Exemplos de IC, NOC, GRL, MCP e observer
├── config/ ├── config/
│ ├── agents.yaml # Registro dos agentes disponíveis │ ├── agents.yaml # Registro e habilitação dos agentes
│ ├── routing.yaml # Intents, keywords, fallback e decisão de rota │ ├── routing.yaml # Intents, keywords, fallback, stickiness e decisão de rota
│ ├── tools.yaml # Catálogo das ferramentas disponíveis para o backend │ ├── tools.yaml # Catálogo funcional das tools e respectivos parâmetros
│ ├── mcp_servers.yaml # Endpoints MCP locais │ ├── tool_policies.yaml # Políticas de execução: confirmação, transação, autorização etc.
│ ├── mcp_servers.docker.yaml # Endpoints MCP em Docker Compose │ ├── mcp_servers.yaml # Endpoints MCP para execução local
│ ├── mcp_parameter_mapping.yaml # Mapeamento entre chaves canônicas e parâmetros das tools │ ├── mcp_servers.docker.yaml # Endpoints MCP para execução em Docker
│ ├── identity.yaml # Resolução de identidade de negócio │ ├── mcp_parameter_mapping.yaml # Mapeamento entre chaves canônicas e parâmetros das tools/MCPs
│ ├── guardrails.yaml # Guardrails globais │ ├── identity.yaml # Resolução e propagação de identidade de negócio
│ ├── judges.yaml # Judges globais │ ├── guardrails.yaml # Configuração de guardrails
│ ├── prompt_policy.yaml # Política global de prompt │ ├── judges.yaml # Configuração de judges
│ └── agents/<agent_id>/ # Configurações isoladas por agente │ └── prompt_policy.yaml # Política global de composição de prompts
├── workflows/
│ ├── devolucao_pedido.active.yaml # Workflow ativo de exemplo
│ └── devolucao_pedido.v1.yaml # Versão declarativa do workflow de exemplo
├── data/ ├── data/
│ └── agent_framework.db # Banco local de exemplo, quando aplicável │ └── agent_framework.db # Banco SQLite local de exemplo para persistência/RAG
├── docs/ # Guias e notas técnicas específicas do template
├── scripts/
│ └── test_long_term_memory.py # Exemplo/teste de Long-Term Memory
├── llm_profiles.yaml # Perfis de LLM consumidos pelo template/framework
├── Dockerfile ├── Dockerfile
├── requirements.txt ├── requirements.txt
└── .env # Configuração local ├── .env.example # Variáveis de ambiente de referência
├── README.md
└── README_ENTERPRISE_TEMPLATE.md
``` ```
> **Importante:** recursos como checkpoint/persistência, Long-Term Memory, RAG genérico, MCP Tool Router, roteamento/supervisor, coleta de parâmetros, reconciliação temporal, idempotência, segurança, Output Supervisor, judges, guardrails e observabilidade corporativa pertencem ao **core do `agent_framework_oci`**. O template apenas os configura, compõe ou estende quando necessário para o domínio.
`tools.yaml` e `tool_policies.yaml` têm responsabilidades diferentes e complementares: o primeiro descreve **quais tools existem e seus contratos/parâmetros**; o segundo define **como e em quais condições elas podem ser executadas**, incluindo confirmação e comportamento transacional.
### 1.1. O que pertence ao framework ### 1.1. O que pertence ao framework
O framework deve concentrar os motores reutilizáveis: O framework deve concentrar os motores reutilizáveis:

View File

@@ -142,41 +142,65 @@ Oracle Cloud Infrastructure Security Best Practice Recommendations.
## 1. Architecture overview ## 1. Architecture overview
The template separates what is generic from what is specific. The `agent_template_backend` keeps the reusable platform engines and services inside `agent_framework_oci` and implements locally only the composition, configuration, and extensions that are specific to the agent/domain. The template is therefore a **reference composition of framework capabilities**, not a duplication of the core.
The current template structure is:
```text ```text
agent_template_backend/ agent_template_backend/
├── app/ ├── app/
│ ├── main.py # FastAPI API, gateway, session, SSE, and workflow input │ ├── main.py # FastAPI, lifecycle, gateway, sessions, SSE, health/readiness, and workflows
│ ├── state.py # LangGraph shared state contract │ ├── state.py # Shared LangGraph state contract
│ ├── workflows/ │ ├── mcp_gateway_client_factory.py # MCP Gateway client creation/configuration
│ │ └── agent_graph.py # Enterprise workflow with router, guardrails, agents, judges, and persistence
│ ├── agents/ │ ├── agents/
│ │ ├── runtime.py # Common resources for agents: MCP, RAG, cache, IC, LLM │ │ ├── runtime.py # Common runtime: LLM, MCP, RAG, memory, cache, and framework capabilities
│ │ ├── billing_agent.py # Example of an invoice agent │ │ ├── prompting.py # Agent prompt/profile composition and application
│ │ ├── product_agent.py # Example of a product agent │ │ ├── billing_agent.py # Billing sample agent
│ │ ├── orders_agent.py # Example of an order agent │ │ ├── product_agent.py # Product sample agent
│ │ └── support_agent.py # Example of a support agent │ │ ├── orders_agent.py # Orders sample agent
│ └── examples/ # Examples of IC, NOC, GRL, MCP, and observer │ │ ├── support_agent.py # Support sample agent
│ │ └── README.md # Agent implementation guidance
│ ├── workflows/
│ │ └── agent_graph.py # LangGraph composition: routing, guardrails, agents, judges, and persistence
│ ├── workflow_actions/
│ │ └── devolucao.py # Deterministic/transactional workflow action example
│ ├── observability/
│ │ └── telemetry_observer.py # Template telemetry/observer integration
│ ├── presentation/
│ │ └── tool_renderers.py # Tool result rendering/presentation
│ └── examples/ # IC, NOC, GRL, MCP, and observer examples
├── config/ ├── config/
│ ├── agents.yaml # Record of available agents │ ├── agents.yaml # Agent registry and enablement
│ ├── routing.yaml # Intents, keywords, fallback and route decision │ ├── routing.yaml # Intents, keywords, fallback, stickiness, and route decision
│ ├── tools.yaml # Catalog of tools available for the backend │ ├── tools.yaml # Functional tool catalog and parameters
│ ├── mcp_servers.yaml # Local MCP endpoints │ ├── tool_policies.yaml # Execution policies: confirmation, transactions, authorization, etc.
│ ├── mcp_servers.docker.yaml # MCP endpoints in Docker Compose │ ├── mcp_servers.yaml # MCP endpoints for local execution
│ ├── mcp_parameter_mapping.yaml # Mapping between canonical keys and tool parameters │ ├── mcp_servers.docker.yaml # MCP endpoints for Docker execution
│ ├── identity.yaml # Business identity resolution │ ├── mcp_parameter_mapping.yaml # Mapping between canonical keys and tool/MCP parameters
│ ├── guardrails.yaml # Global guardrails │ ├── identity.yaml # Business identity resolution and propagation
│ ├── judges.yaml # Global judges │ ├── guardrails.yaml # Guardrail configuration
│ ├── prompt_policy.yaml # Global prompt policy │ ├── judges.yaml # Judge configuration
│ └── agents/<agent_id>/ # Isolated settings by agent │ └── prompt_policy.yaml # Global prompt composition policy
├── workflows/
│ ├── devolucao_pedido.active.yaml # Active sample workflow
│ └── devolucao_pedido.v1.yaml # Declarative version of the sample workflow
├── data/ ├── data/
│ └── agent_framework.db # Local sample database, when applicable │ └── agent_framework.db # Local SQLite sample database for persistence/RAG
├── docs/ # Template-specific guides and technical notes
├── scripts/
│ └── test_long_term_memory.py # Long-Term Memory example/test
├── llm_profiles.yaml # LLM profiles consumed by the template/framework
├── Dockerfile ├── Dockerfile
├── requirements.txt ├── requirements.txt
└── .env # Local configuration ├── .env.example # Reference environment variables
├── README.md
└── README_ENTERPRISE_TEMPLATE.md
``` ```
> **Important:** capabilities such as checkpoint/persistence, Long-Term Memory, generic RAG, MCP Tool Router, routing/supervisor, parameter collection, temporal reconciliation, idempotency, security, Output Supervisor, judges, guardrails, and enterprise observability belong to the **`agent_framework_oci` core**. The template only configures, composes, or extends them when required by the domain.
`tools.yaml` and `tool_policies.yaml` have different and complementary responsibilities: the former describes **which tools exist and their contracts/parameters**; the latter defines **how and under which conditions they may execute**, including confirmation and transactional behavior.
### 1.1. What belongs to the framework ### 1.1. What belongs to the framework
The framework should concentrate the reusable engines: The framework should concentrate the reusable engines:

View File

@@ -143,6 +143,34 @@ Examples:
If the core needs to import a concrete agent module in order to work, this separation has probably been broken. If the core needs to import a concrete agent module in order to work, this separation has probably been broken.
### Agent extension folders in the template
`agent_template_backend` materializes selected framework extension points as local folders. These folders **do not duplicate the core**: they hold declarative configuration or domain-specific implementation that is registered with or consumed by generic `agent_framework` mechanisms.
```text
templates/agent_template_backend/
├── workflows/
│ ├── <workflow>.vN.yaml # versioned deterministic workflow definition
│ └── <workflow>.active.yaml # active version selected by the agent
└── app/
├── workflow_actions/ # business actions invoked by workflow YAML files
├── presentation/ # domain-specific deterministic renderers
└── observability/ # local telemetry observers/adapters and integration
```
The architectural boundary is:
| Template folder | Should contain | Remains in the core |
| --- | --- | --- |
| `workflows/` | declarative, versioned domain YAML files | parser, validation, registry, executor, pause/resume, and workflow runtime |
| `app/workflow_actions/` | business functions registered with `@workflow_action` | decorator, registry, execution, retry policy, and idempotency infrastructure |
| `app/presentation/` | renderers that turn trusted results into domain responses | renderer registry, response-mode selection, and runtime fallback |
| `app/observability/` | agent-specific observer/adapters, mappings, and enrichment | IC/NOC/GRL contracts, correlation, OTEL/Langfuse, exporters, and observability runtime |
Practical rule: if an implementation could be reused without knowing a specific telecom, retail, billing, order, or other business domain, it likely belongs in `agent_framework`, not in one of these agent folders. The core must also never import concrete modules from these folders; the agent registers its extensions during startup.
See: [Transactional Workflows and State](./03_transaction_workflows_and_state.md), [Advanced transactional workflows](./13_advanced_transactional_workflows.md), [Observability, Persistence, and Operational Readiness](./11_observability_persistence_and_operational_readiness.md), and [Presentation, recovery, and observability](./15_presentation_recovery_and_observability.md).
### State, memory, and checkpoint are different concepts ### State, memory, and checkpoint are different concepts
**Execution state** represents what is happening in the turn and workflow. **Execution state** represents what is happening in the turn and workflow.

View File

@@ -256,6 +256,27 @@ Esperado: active_transaction é restaurado e concluído sem reiniciar a tool.
- `Tuning-Performance/Transaction_Pre_Validation/` - `Tuning-Performance/Transaction_Pre_Validation/`
- `Tuning-Performance/Transaction_Evidence/` - `Tuning-Performance/Transaction_Evidence/`
### Physical organization of `workflows/` in the template
In `agent_template_backend`, declarative definitions live in the agent's root `workflows/` folder:
```text
templates/agent_template_backend/
└── workflows/
├── devolucao_pedido.v1.yaml
└── devolucao_pedido.active.yaml
```
This folder belongs to the **agent** because it expresses domain-specific business sequencing, versions, and decisions. The mechanism that interprets these files belongs to the **framework**. Therefore:
- do not implement parsers, executors, or registries inside `workflows/`;
- do not place Python code there; Python actions belong in `app/workflow_actions/`;
- keep immutable versions (`*.vN.yaml`) and a valid active definition (`*.active.yaml`);
- use `WORKFLOWS_PATH` when a host must point to another directory;
- generic pause/resume, retry, validation, or execution changes belong in `agent_framework.workflows`, not in copied template code.
The complete path is: **YAML in `workflows/` → framework engine → `node.action` → action registry → function in `app/workflow_actions/`**.
### Transactional workflow engine architectural decision ### Transactional workflow engine architectural decision
> Content consolidated from `docs/ADR_TRANSACTIONAL_WORKFLOW_ENGINE.md`. > Content consolidated from `docs/ADR_TRANSACTIONAL_WORKFLOW_ENGINE.md`.

View File

@@ -687,6 +687,44 @@ Validations performed:
Note: Note:
- The gateway SSE proxy was left as a future step. The `/gateway/message/sse` endpoint already routes and forwards as a normal message; for end-to-end SSE, a proxy from `/gateway/events/{session_id}` to the active backend can be implemented. - The gateway SSE proxy was left as a future step. The `/gateway/message/sse` endpoint already routes and forwards as a normal message; for end-to-end SSE, a proxy from `/gateway/events/{session_id}` to the active backend can be implemented.
### Role of `app/observability/` in an agent
The framework contains generic observability infrastructure; the template contains only the agent-specific integration point. In `agent_template_backend`, the reference structure is:
```text
app/observability/
├── __init__.py
└── telemetry_observer.py
```
`app/observability/` is appropriate for:
- constructing/configuring the observer used by the agent;
- enriching events with host-specific metadata;
- adapting the agent contract to external integrations;
- registering template callbacks/adapters;
- applying agent-specific mappings/overlays when configuration supports them.
It must **not** contain a second implementation of OpenTelemetry, Langfuse, IC/NOC/GRL, sequence, exporters, correlation, or persistence. Those are cross-cutting mechanisms owned by `agent_framework`.
Expected dependency direction:
```text
app/observability/telemetry_observer.py
│ configures/composes
▼
agent_framework.observability + shared contracts
│
├── Langfuse
├── OpenTelemetry
├── IC / NOC / GRL
└── exporters / mappings / pub-sub
```
When creating a new agent, prefer reusing the reference adapter and changing only configuration/domain metadata. If multiple agents need the same change, implement it in the core and keep `app/observability/` thin.
**Anti-patterns:** importing telemetry SDKs directly in every agent to emit equivalent events; hardcoding historical labels in the agent runtime; using observability events as the source of truth for transaction state; sending full prompts, secrets, PII, or raw financial payloads.
### Source files ### Source files
The files below were consolidated into this manual: The files below were consolidated into this manual:

View File

@@ -67,6 +67,37 @@ Store definitions under `workflows/<name>.vN.yaml` and maintain a valid active d
Agent actions use `@workflow_action("name")`, matching `node.action`, and implement `(params: dict, state: dict) -> dict`. Import the action module during startup so decorators register. Return serializable data only—never an HTTP client, connection, exception, or coroutine. Complete executable YAML and Python are available in the matching [Portuguese chapter](../pt/13_workflows_transacionais_avancados.md). Agent actions use `@workflow_action("name")`, matching `node.action`, and implement `(params: dict, state: dict) -> dict`. Import the action module during startup so decorators register. Return serializable data only—never an HTTP client, connection, exception, or coroutine. Complete executable YAML and Python are available in the matching [Portuguese chapter](../pt/13_workflows_transacionais_avancados.md).
### Organization of `app/workflow_actions/`
In the template, domain-specific actions live in `app/workflow_actions/`. The distributed example uses:
```text
app/workflow_actions/
├── __init__.py
└── devolucao.py
```
This directory should contain **only business implementation invoked by workflows** and small helpers directly related to those actions. The workflow engine, decorator, registry, persistence, pause/resume mechanism, and generic idempotency infrastructure remain in `agent_framework`.
A larger agent can split actions by domain or aggregate:
```text
app/workflow_actions/
├── billing.py
├── orders.py
└── vas.py
```
Rules:
- YAML `node.action` must match the name registered with `@workflow_action`;
- import required modules during startup so the registry is populated before first execution;
- never make the core import `app.workflow_actions.*`; dependency direction is agent → framework;
- do not turn an action into a second router or agent runtime; it should perform one bounded business step;
- for external side effects, use framework policy/idempotency infrastructure and persist only confirmed outcomes.
**Anti-pattern:** copying `agent_framework.workflows` classes into `app/workflow_actions/` to customize a local case. If a generic mechanism is missing, extend the framework through a reusable interface and keep only domain rules in the agent.
### Idempotent external effects ### Idempotent external effects
Create one `create_idempotency_store(...)` instance at startup and inject it into actions. Build the key from stable business identity, operation, resource, and contract version—not merely a timestamp. `IDEMPOTENCY_PROVIDER` takes precedence over checkpoint, session, and cache providers. For production transactions, enable `IDEMPOTENCY_REQUIRE_DURABLE=true` and select an appropriate `oracle`, `redis`, or `sqlite` provider. Memory does not protect across pods or restarts. Persist the outcome only after the external system confirms the effect. Create one `create_idempotency_store(...)` instance at startup and inject it into actions. Build the key from stable business identity, operation, resource, and contract version—not merely a timestamp. `IDEMPOTENCY_PROVIDER` takes precedence over checkpoint, session, and cache providers. For production transactions, enable `IDEMPOTENCY_REQUIRE_DURABLE=true` and select an appropriate `oracle`, `redis`, or `sqlite` provider. Memory does not protect across pods or restarts. Persist the outcome only after the external system confirms the effect.

View File

@@ -4,6 +4,27 @@
Use `response.mode: renderer` for trusted structured tool results whose values must not be changed by an LLM. Register each renderer once at startup. Its keyword-only contract accepts `tool_name`, `result`, `state`, and `agent_label`; return `None` when required fields are absent so the configured fallback can run. Select, format, and mask allowed fields—never interpolate the complete payload. The executable YAML and implementation are in the matching [Portuguese chapter](../pt/15_apresentacao_recuperacao_e_observabilidade.md). Use `response.mode: renderer` for trusted structured tool results whose values must not be changed by an LLM. Register each renderer once at startup. Its keyword-only contract accepts `tool_name`, `result`, `state`, and `agent_label`; return `None` when required fields are absent so the configured fallback can run. Select, format, and mask allowed fields—never interpolate the complete payload. The executable YAML and implementation are in the matching [Portuguese chapter](../pt/15_apresentacao_recuperacao_e_observabilidade.md).
### Organization of `app/presentation/`
In `agent_template_backend`, domain-specific renderers live in:
```text
app/presentation/
├── __init__.py
└── tool_renderers.py
```
The folder separates **how a trusted domain result should be presented** from the generic infrastructure that selects and executes renderers. Therefore:
- `app/presentation/` implements functions such as `financial.balance`, `billing.invoice`, or another agent-specific renderer;
- `agent_framework.presentation` owns the registry, call contract, and generic runtime integration;
- `config/tools.yaml` selects `response.mode: renderer` and the renderer name;
- agent startup imports/registers renderers once.
Renderers must not fetch data, decide authorization, execute tools, mutate transactional state, or reinterpret a result with an LLM. Their input should already be an authorized/trusted result; the renderer only selects, masks, and formats fields.
**Anti-pattern:** building a copy of the framework presentation registry or pipeline inside `app/presentation/`. If several agents need the same formatting/selection mechanism, evolve it in the core; only domain-specific presentation remains in the agent.
### Output supervision and recovery ### Output supervision and recovery
The Output Supervisor may allow, sanitize, retry, block, hand over, or observe candidate output. Keep retries bounded, provide objective retry guidance, and revalidate rewritten output. Permanent authorization or dependency failure is not a content retry. The Output Supervisor may allow, sanitize, retry, block, hand over, or observe candidate output. Keep retries bounded, provide objective retry guidance, and revalidate rewritten output. Permanent authorization or dependency failure is not a content retry.

View File

@@ -144,6 +144,34 @@ Exemplos:
Se o core precisa importar um módulo concreto do agente para funcionar, essa separação provavelmente foi quebrada. Se o core precisa importar um módulo concreto do agente para funcionar, essa separação provavelmente foi quebrada.
### Pastas de extensão do agente no template
O `agent_template_backend` materializa alguns pontos de extensão do framework em pastas locais. Essas pastas **não duplicam o core**: elas contêm configuração declarativa ou implementação específica do domínio que é registrada/consumida pelos mecanismos genéricos de `agent_framework`.
```text
templates/agent_template_backend/
├── workflows/
│ ├── <workflow>.vN.yaml # definição versionada do fluxo determinístico
│ └── <workflow>.active.yaml # versão ativa selecionada pelo agente
└── app/
├── workflow_actions/ # actions de negócio chamadas pelos workflows YAML
├── presentation/ # renderers determinísticos específicos do domínio
└── observability/ # adapters/observers e integração local de telemetria
```
A fronteira arquitetural é:
| Pasta do template | Deve conter | Permanece no core |
| --- | --- | --- |
| `workflows/` | YAMLs declarativos e versionados do domínio | parser, validação, registry, executor, pause/resume e runtime de workflow |
| `app/workflow_actions/` | funções de negócio registradas com `@workflow_action` | decorator, registry, execução, política de retry e infraestrutura de idempotência |
| `app/presentation/` | renderers que transformam resultados confiáveis em resposta de domínio | registry de renderers, seleção do modo de resposta e fallback do runtime |
| `app/observability/` | observer/adapters, mappings e enriquecimento específicos do agente | contratos IC/NOC/GRL, correlação, OTEL/Langfuse, exporters e runtime de observabilidade |
Regra prática: se uma implementação poderia ser usada sem conhecer telecom, varejo, cobrança, pedido ou outro domínio específico, ela provavelmente pertence ao `agent_framework`, e não a uma dessas pastas do agente. O core também não deve importar módulos concretos dessas pastas; o agente registra suas extensões no startup.
Detalhes: [Workflows Transacionais e Estado](./03_transaction_workflows_and_state.md), [Workflows transacionais avançados](./13_workflows_transacionais_avancados.md), [Observabilidade, Persistência e Prontidão Operacional](./11_observability_persistence_and_operational_readiness.md) e [Apresentação, recuperação e observabilidade](./15_apresentacao_recuperacao_e_observabilidade.md).
### Estado, memória e checkpoint são conceitos diferentes ### Estado, memória e checkpoint são conceitos diferentes
**Estado de execução** representa o que está acontecendo no turno e no workflow. **Estado de execução** representa o que está acontecendo no turno e no workflow.

View File

@@ -257,6 +257,27 @@ Esperado: active_transaction é restaurado e concluído sem reiniciar a tool.
- `Tuning-Performance/Transaction_Pre_Validation/` - `Tuning-Performance/Transaction_Pre_Validation/`
- `Tuning-Performance/Transaction_Evidence/` - `Tuning-Performance/Transaction_Evidence/`
### Organização física de `workflows/` no template
No `agent_template_backend`, as definições declarativas ficam na raiz `workflows/` do próprio agente:
```text
templates/agent_template_backend/
└── workflows/
├── devolucao_pedido.v1.yaml
└── devolucao_pedido.active.yaml
```
Essa pasta pertence ao **agente**, porque expressa a sequência de negócio, versões e decisões daquele domínio. O mecanismo que interpreta esses arquivos pertence ao **framework**. Portanto:
- não implemente parser, executor ou registry dentro de `workflows/`;
- não coloque código Python nessa pasta; actions Python ficam em `app/workflow_actions/`;
- mantenha versões imutáveis (`*.vN.yaml`) e uma definição ativa válida (`*.active.yaml`);
- use `WORKFLOWS_PATH` quando o host precisar apontar para outro diretório;
- mudanças genéricas em pause/resume, retry, validação ou execução devem ser feitas no módulo `agent_framework.workflows`, não copiadas para o template.
O fluxo completo é: **YAML em `workflows/` → engine do framework → `node.action` → registry de actions → função em `app/workflow_actions/`**.
### Decisão arquitetural do motor de workflows ### Decisão arquitetural do motor de workflows
> Conteúdo consolidado a partir de `docs/ADR_TRANSACTIONAL_WORKFLOW_ENGINE.md`. > Conteúdo consolidado a partir de `docs/ADR_TRANSACTIONAL_WORKFLOW_ENGINE.md`.

View File

@@ -683,6 +683,44 @@ Validações executadas:
Observação: Observação:
- O proxy SSE do gateway foi deixado como etapa futura. O endpoint /gateway/message/sse já roteia e encaminha como mensagem normal; para SSE fim-a-fim, pode-se implementar proxy de /gateway/events/{session_id} para o backend ativo. - O proxy SSE do gateway foi deixado como etapa futura. O endpoint /gateway/message/sse já roteia e encaminha como mensagem normal; para SSE fim-a-fim, pode-se implementar proxy de /gateway/events/{session_id} para o backend ativo.
### Papel de `app/observability/` no agente
O framework contém a infraestrutura genérica de observabilidade; o template contém apenas o ponto de integração específico do agente. No `agent_template_backend`, a estrutura de referência é:
```text
app/observability/
├── __init__.py
└── telemetry_observer.py
```
`app/observability/` é apropriado para:
- construir/configurar o observer usado pelo agente;
- enriquecer eventos com metadados específicos disponíveis no host;
- adaptar o contrato do agente a integrações externas;
- registrar callbacks/adapters do template;
- aplicar mappings/overlays específicos do agente quando previstos por configuração.
Ele **não** deve conter uma segunda implementação de OpenTelemetry, Langfuse, IC/NOC/GRL, sequence, exporters, correlação ou persistência. Esses mecanismos são transversais e pertencem ao `agent_framework`.
A dependência esperada é:
```text
app/observability/telemetry_observer.py
│ configura/compõe
▼
agent_framework.observability + contratos compartilhados
│
├── Langfuse
├── OpenTelemetry
├── IC / NOC / GRL
└── exporters / mappings / pub-sub
```
Ao criar um novo agente, prefira reutilizar o adapter de referência e alterar somente configuração/metadados de domínio. Se uma mudança for necessária para vários agentes, implemente-a no core e mantenha `app/observability/` fino.
**Anti-padrões:** importar diretamente SDKs de telemetria em cada agente para emitir eventos equivalentes; codificar labels históricos no runtime do agente; usar eventos de observabilidade como fonte de verdade do estado transacional; enviar prompt integral, segredo, PII ou payload financeiro bruto.
### Arquivos de origem ### Arquivos de origem
Os arquivos abaixo foram consolidados neste manual: Os arquivos abaixo foram consolidados neste manual:

View File

@@ -114,6 +114,37 @@ async def registrar_devolucao(params: dict, state: dict) -> dict:
O nome do decorator deve ser igual a `node.action`. A assinatura obrigatória é `(params: dict, state: dict) -> dict`. O módulo precisa ser importado no startup para registrar decorators. Actions devem devolver dados serializáveis; não devolva cliente HTTP, conexão, exception ou coroutine. O nome do decorator deve ser igual a `node.action`. A assinatura obrigatória é `(params: dict, state: dict) -> dict`. O módulo precisa ser importado no startup para registrar decorators. Actions devem devolver dados serializáveis; não devolva cliente HTTP, conexão, exception ou coroutine.
### Organização de `app/workflow_actions/`
No template, actions específicas do domínio ficam em `app/workflow_actions/`. O exemplo distribuído usa:
```text
app/workflow_actions/
├── __init__.py
└── devolucao.py
```
Esse diretório deve conter **somente implementação de negócio acionável pelo workflow** e pequenas funções auxiliares diretamente relacionadas. O motor de workflows, o decorator, o registry, a persistência, o mecanismo de pause/resume e a infraestrutura genérica de idempotência continuam no `agent_framework`.
Uma organização maior pode separar actions por domínio ou agregado:
```text
app/workflow_actions/
├── billing.py
├── orders.py
└── vas.py
```
Regras:
- o `node.action` do YAML deve corresponder ao nome registrado em `@workflow_action`;
- importe os módulos necessários no startup para que o registry seja populado antes da primeira execução;
- não faça o core importar `app.workflow_actions.*`; o sentido da dependência é do agente para o framework;
- não use a action como um segundo router ou como um novo runtime de agentes; ela deve executar uma etapa de negócio bem delimitada;
- para efeitos externos, use a política e a infraestrutura de idempotência do framework e persista apenas resultados confirmados.
**Anti-padrão:** copiar classes de `agent_framework.workflows` para `app/workflow_actions/` para customizar um caso local. Se o mecanismo genérico não atende, estenda o framework por uma interface reutilizável; mantenha apenas a regra específica no agente.
### Idempotência do efeito externo ### Idempotência do efeito externo
```python idempotency-example ```python idempotency-example

View File

@@ -37,6 +37,27 @@ def register_financial_renderers() -> None:
Importe e execute `register_financial_renderers()` uma vez no startup. A assinatura é keyword-only e deve aceitar `tool_name`, `result`, `state` e `agent_label`. Retorne `None` quando faltarem campos obrigatórios para permitir o fallback previsto pelo runtime. Nunca interpolar o payload inteiro: selecione campos permitidos, mascare identidade e formate valores explicitamente. Importe e execute `register_financial_renderers()` uma vez no startup. A assinatura é keyword-only e deve aceitar `tool_name`, `result`, `state` e `agent_label`. Retorne `None` quando faltarem campos obrigatórios para permitir o fallback previsto pelo runtime. Nunca interpolar o payload inteiro: selecione campos permitidos, mascare identidade e formate valores explicitamente.
### Organização de `app/presentation/`
No `agent_template_backend`, renderers específicos do domínio ficam em:
```text
app/presentation/
├── __init__.py
└── tool_renderers.py
```
A pasta existe para separar **como um resultado confiável do domínio deve ser apresentado** da infraestrutura genérica que seleciona e executa renderers. Assim:
- `app/presentation/` implementa funções como `financial.balance`, `billing.invoice` ou outro renderer específico do agente;
- `agent_framework.presentation` mantém registry, contrato de chamada e mecanismo genérico de integração com o runtime;
- `config/tools.yaml` seleciona `response.mode: renderer` e o nome do renderer;
- o startup do agente importa/registra os renderers uma única vez.
Renderers não devem buscar dados, decidir autorização, executar tools, alterar estado transacional ou reinterpretar um resultado usando LLM. A entrada já deve representar um resultado autorizado/confiável; o renderer apenas seleciona, mascara e formata campos.
**Anti-padrão:** criar em `app/presentation/` uma cópia do registry ou do pipeline de apresentação do framework. Se vários agentes precisarem do mesmo mecanismo de formatação/seleção, ele deve evoluir no core; somente a apresentação específica do domínio fica no agente.
### Output Supervisor ### Output Supervisor
O Output Supervisor valida a resposta candidata antes da saída final. Ele pode permitir, sanitizar, solicitar retry, bloquear, entregar a humano ou observar. `OUTPUT_SUPERVISOR_MAX_RETRIES` deve ter limite pequeno; cada retry precisa de orientação objetiva e a resposta reescrita deve passar novamente pelos controles. Não use retry para erro permanente de autorização ou indisponibilidade. O Output Supervisor valida a resposta candidata antes da saída final. Ele pode permitir, sanitizar, solicitar retry, bloquear, entregar a humano ou observar. `OUTPUT_SUPERVISOR_MAX_RETRIES` deve ter limite pequeno; cada retry precisa de orientação objetiva e a resposta reescrita deve passar novamente pelos controles. Não use retry para erro permanente de autorização ou indisponibilidade.