Files
agent_platform_oci/MANUAL_RULES_AGENT_TEMPLATE_BACKEND_EN.md

83 KiB

Detailed Rule Manual for agent_template_backend

Technical Preface — how the agent_template_backend decision engine works

agent_template_backend is a corporate reference template for building agents on the Agent Framework OCI. Decision logic is not concentrated in one if, prompt, or router. Final behavior results from cooperation among declarative configuration, LangGraph state, transactional runtime, MCP Tool Router, RAG, memory, guardrails, judges, Output Supervisor, workflows, and persistence.

A message may:

  • be sanitized/blocked before routing;
  • belong to an already-open transaction;
  • fill a pending parameter;
  • confirm/reject an action;
  • interrupt the previous operation through intent shift;
  • continue with the current agent through route stickiness;
  • contain multiple independent intents;
  • resume a paused workflow;
  • select one or more candidate tools;
  • go through pre-validation;
  • change its execution path because of policy;
  • execute a tool directly or a deterministic workflow;
  • use MCP as operational evidence;
  • use RAG as documentary knowledge;
  • use summarized/long-term memory as context;
  • be reviewed by Output Supervisor, guardrails, and judges;
  • persist state/evidence for the next turn.

When diagnosing the template, the right question is not only “which intent was found?” but:

What state was the session in, which mechanism had precedence, which intent/route won, which tool was selected, which parameters were resolved, which policy/pre-validation applied, what execution occurred, and which evidence supported the final response?

P.1. Engine overview

flowchart TD
    U["Message / GatewayRequest"] --> IGR["Input Guardrails"]
    IGR --> LTM["Load Long-Term Memory"]
    LTM --> RT["EnterpriseRouter / Supervisor"]
    RT --> CP["Conversation policy / state precedence"]
    CP --> AG["Domain agent"]
    AG --> TP["Tool policy + parameters"]
    TP --> PV["Pre-validation when configured"]
    PV --> CF["Confirmation when transactional"]
    CF --> EX["Direct MCP or Workflow"]
    EX --> RAG["RAG when needed"]
    RAG --> CMP["Response composition"]
    CMP --> OS["Output Supervisor"]
    OS --> OGR["Output Guardrails"]
    OGR --> J["Judges"]
    J --> SR["Supervisor Review"]
    SR --> MEM["Persistence / memory / checkpoint"]
    MEM --> F["Response"]

Not every turn traverses every layer. A tracking query may finish quickly with MCP + renderer; a return may require collection, confirmation, and workflow execution.

P.2. Actual corporate graph in the template

app/workflows/agent_graph.py builds a FrameworkStateGraph(AgentState) with the main nodes:

START
  ↓
input_guardrails
  ↓
load_long_term_memory
  ↓
routing_decision
  ↓
billing_agent | product_agent | orders_agent | support_agent
     | handoff | human_handoff | end_session | supervisor_agent
  ↓
output_supervisor
  ↓
output_guardrails
  ↓
judge
  ↓
supervisor_review
  ↓
persist_long_term_memory
  ↓
persist
  ↓
END

The graph is the backbone; domain rules live in YAML, agents, MCP, and workflows.

P.3. Three state families

P.3.1. States declared in routing.yaml

State Owning agent
WAITING_BILLING_CONFIRMATION billing_agent
WAITING_PRODUCT_CONFIRMATION product_agent
WAITING_ORDER_CONFIRMATION orders_agent
WAITING_SUPPORT_CONFIRMATION support_agent
COLLECTING_BILLING_PARAMETERS billing_agent
COLLECTING_PRODUCT_PARAMETERS product_agent
COLLECTING_ORDER_PARAMETERS orders_agent
COLLECTING_SUPPORT_PARAMETERS support_agent

They keep the next turn with the owning agent while parameters or confirmation are pending.

P.3.2. Canonical transactional runtime states

The runtime uses states such as:

COLLECTING_PARAMETERS
AWAITING_CONFIRMATION
CONFIRMED
EXECUTING
WORKFLOW_PAUSED
TOOL_RESULT_CLARIFICATION
COMPLETED
FAILED
CANCELLED
BLOCKED
OUT_OF_SCOPE

These control parameters, confirmation, execution, and transaction termination.

P.3.3. Workflow-engine states

A workflow has an independent execution identified by execution_id, with results such as:

PAUSED / WAITING_INPUT
COMPLETED
FAILED

The three groups are related, but they must not be treated as a single enum.

P.4. Conceptual transactional state machine

stateDiagram-v2
    [*] --> COLLECTING_PARAMETERS: required fields missing
    COLLECTING_PARAMETERS --> AWAITING_CONFIRMATION: complete parameters + validations OK
    COLLECTING_PARAMETERS --> CANCELLED: intent shift / abandonment

    AWAITING_CONFIRMATION --> EXECUTING: positive confirmation
    AWAITING_CONFIRMATION --> CANCELLED: negative confirmation
    AWAITING_CONFIRMATION --> AWAITING_CONFIRMATION: inconclusive response

    EXECUTING --> COMPLETED: tool/workflow completed
    EXECUTING --> WORKFLOW_PAUSED: workflow requests input
    EXECUTING --> FAILED: technical error
    EXECUTING --> BLOCKED: policy/guardrail
    EXECUTING --> OUT_OF_SCOPE: domain rule rejects

    WORKFLOW_PAUSED --> EXECUTING: valid resume
    WORKFLOW_PAUSED --> COMPLETED: workflow ends

P.5. Routing

config/routing.yaml is the declarative source for intents, priorities, agents, tools, keywords, and examples.

The main EnterpriseRouter sequence is:

active state/transaction
→ deterministic matching
→ LLM router when enabled
→ fallback

Deterministic matching favors the best priority/specificity combination; lower numeric priority values take precedence.

When ENABLE_LLM_ROUTER=true, the LLM receives the allowed catalog and classifies within it. The LLM must not invent new tools or agents.

P.6. Route stickiness

ENABLE_ROUTE_STICKINESS enables a lightweight classifier that decides semantic continuity among:

CONTINUE
ROUTE
HUMAN_HANDOFF
END_SESSION

Relevant configuration:

ROUTE_STICKINESS_LLM_PROFILE
ROUTE_STICKINESS_CONFIDENCE_THRESHOLD
ROUTE_STICKINESS_HISTORY_TURNS
ROUTE_STICKINESS_MAX_TOKENS

CONTINUE keeps the active agent; ROUTE goes back to EnterpriseRouter. Stickiness does not authorize transactions and does not replace tool policy.

P.7. Intent shift

During COLLECTING_PARAMETERS or AWAITING_CONFIRMATION, the framework protects the current transaction from accidental topic changes. An explicit change of subject may, however, cancel/clear the transactional latch and return the turn to normal routing.

The current utterance also has precedence when filling pending fields. A response such as PED-1001 while collecting order_id must not be reinterpreted as a new intent.

P.8. Parameter collection

Parameter requirements are produced by the combination:

tools.yaml args_schema
+ tool_policies.yaml requires
+ mcp_parameter_mapping.yaml
+ canonical state data

Example:

cancelar_pedido
requires: [order_id]

Without order_id, the runtime enters COLLECTING_PARAMETERS, uses the tool schema/user prompt to request the field, and preserves agent ownership.

P.9. Temporal reconciliation

The framework contains a temporal reconciler in runtime/transaction_parameters.py. It is used after the normal current-turn extraction attempt when required fields are still missing.

Principles:

  • the current utterance is the newest source and has precedence;
  • history resolves references but does not invent operational facts;
  • fields may be preserved, resolved, cleared, or remain unresolved;
  • ambiguity must remain unresolved;
  • candidate results still pass domain validations/pre-validation.

This allows coherent cross-turn relationships without converting conversational history into backend evidence.

P.10. Contextual reentry

EnterpriseRouter and the runtime support contextual_reentry: a short turn may reenter a rule when the immediately preceding context constrains its meaning.

The runtime keeps the current utterance separate from relevant_conversation_context; that context is interpretive and does not replace tools/MCP as operational authority.

P.11. Multi-intent and pending_topics

MultiIntentPlanner can split independent goals:

"track the order and then cancel it"

into distinct topics without decomposing internal parameters of one action.

When one action must finish before the next, remaining goals may be persisted in pending_topics. drain_pending_topics() appears directly in the template graph.

P.12. Tool policies

tools.yaml describes capabilities. tool_policies.yaml describes how a sensitive capability may execute.

In the base template:

  • cancelar_pedido: transactional + confirmation + order_id + pre-validation;
  • solicitar_troca: transactional + confirmation;
  • solicitar_devolucao: transactional + confirmation + order_id/reason + workflow.

This prevents sensitive execution rules from being hardcoded inside agents.

P.13. Pre-validation

Pre-validation occurs after required parameters are complete and before confirmation.

Flow:

complete parameters
→ side-effect-free MCP validator
→ eligible?
   ├─ false: OUT_OF_SCOPE / terminate latch
   └─ true: AWAITING_CONFIRMATION

In the template, cancelar_pedido uses validar_cancelamento_pedido with fail_open=false.

P.14. Transaction confirmation

Tools with require_confirmation=true do not execute automatically.

The framework first attempts to interpret explicit confirmations deterministically and can use semantic fallback when necessary. A positive response promotes the transaction to execution; a negative one cancels it; an inconclusive response keeps the transaction active.

P.15. Transactional workflow

A policy may define:

execution:
  mode: workflow
  workflow: devolucao_pedido
  version: active

After confirmation, the logical tool is executed by WorkflowToolExecutor, which loads the versioned YAML and executes the deterministic graph. The domain declares nodes/actions; the framework owns runtime, checkpointing, and tracing.

P.16. Pause/Resume

The workflow engine supports pause nodes, expected_input, resume_from, and resume by execution_id. The base return workflow does not pause; the capability is demonstrated separately in Tuning-Performance/Pause_Resume_Workflow.

An important rule is that pause compilation must not automatically rerun a side-effecting action when the user answers.

P.17. Guardrails

In the global template:

Input

  • MSK
  • VLOOP

Output

  • REVPREC
  • PINJ
  • DLEX_OUT

Pipelines can be enabled/disabled through .env. Guardrails evaluate permission/safety/operational coherence; they must not replace routing or domain rules.

P.18. Output Supervisor

Output Supervisor sits between the agent and output guardrails. It may review the candidate response, apply retry/sanitize/block/handover policies, and prevent premature claims about effects that are not supported by operational results.

OUTPUT_SUPERVISOR_MAX_RETRIES controls the regeneration limit.

P.19. Judges

config/judges.yaml enables:

Judge Threshold/policy
response_quality 0.7
groundedness 0.6
sentiment does not fail on negative
tone fail_closed=true

Global configuration:

enabled=true
fail_closed=true
sample_rate=0.25
always_run_for_transactional=true

Transactional responses are therefore evaluated even when the general sampling rate would skip them.

P.20. MCP, operational evidence, and renderers

The template separates three responsibilities:

routing → which capabilities belong to the intent
tool runtime → which capability should actually execute
MCP server → operational fact / integration

Some tools use response.mode: renderer, such as telecom.invoice, telecom.plan, retail.order, and retail.delivery. In those cases, MCP results may be presented deterministically without requiring LLM composition.

P.21. RAG

AgentRuntimeMixin._retrieve_rag_context() uses the framework's official RAG path. RAG is for documentary knowledge; MCP is for operational state.

The runtime also supports Domain-Requested RAG: a tool may return requires_rag=true and rag_queries, forcing retrieval even when MCP would normally be considered sufficient.

P.22. Domain-requested LLM composition

A tool/workflow may return:

{
  "requires_llm_composition": true,
  "response_instruction": "Explain using only workflow evidence."
}

The domain does not create its own LLM gateway. AgentRuntime uses the official provider, preserving tracing, cost controls, profiles, and guardrails.

P.23. Memory

The template provides:

  • ConversationSummaryMemory;
  • recent memory;
  • optional Long-Term Memory;
  • operational checkpoint/persistence.

Memory helps interpret context, preferences, and continuity. It does not replace Transaction Evidence or MCP for asserting that an operation occurred.

P.24. Transaction Evidence

Completed transaction results can be persisted as structured operational evidence and correlated with future turns. This prevents later responses from mentioning a previous protocol/cancellation without providing the same evidence to judges/groundedness.

P.25. Idempotency

Transactional state, checkpointing, and execution_id also protect against retry/replay/reexecution. A repeated confirmation must not create two transactions just because the channel resent a message.

P.26. Voice interruption and replay

The framework contains channel short-circuits for idle nudges, non-interruptible speech, post-finalization, and barge-in. In several cases it simply replays the last utterance without reopening LangGraph, tools, or guardrails; where needed it uses the processing_interruption_classifier profile.

P.27. Workflow error and recovery

WorkflowRuntime preserves the last valid snapshot and exposes error, partial trace, and error_details when the provider supplies status_code, body, and attempts. The domain can distinguish technical failure from business-rule rejection without coupling the framework to the provider.

P.28. Observability

The template emits telemetry to:

  • Langfuse;
  • OpenTelemetry;
  • corporate analytics/observer;
  • IC events;
  • NOC;
  • GRL;
  • workflow;
  • guardrails;
  • judges.

Telemetry should allow reconstruction of:

input → route → agent → tool → policy → workflow → output controls → persistence

P.29. agents.yaml: logical application/agent isolation

config/agents.yaml registers two reference agent_id values:

  • telecom_contas;
  • retail_orders.

Each can point to prompt policy, routing, guardrails, judges, MCP servers, and tools, plus metadata.system_prefix. The goal is to prevent policies, memory/checkpoints, or decisions from leaking across logical identities.

P.30. Troubleshooting golden rule

Always investigate in this order:

1. Which agent_id is active?
2. What was the state/checkpoint?
3. Was there an active transaction or paused workflow?
4. Which route/stickiness decision occurred?
5. Which intent won and why?
6. Which mcp_tools did the intent authorize?
7. Which tool was actually selected?
8. Which parameters were resolved?
9. Did temporal reconciliation occur?
10. Did pre-validation occur?
11. Was confirmation required?
12. Direct tool or workflow?
13. Which MCP/workflow result was produced?
14. Did the response use renderer, RAG, or LLM?
15. Did Output Supervisor/guardrails change anything?
16. Did judges approve it?
17. Was state/evidence persisted?

This is the engine on which the template's five rules are built.

1. How to read this manual

This manual follows the same model as the Accounts Agent manual. Each rule is explained at six levels:

  1. Rule/intent — what it means and its boundary.
  2. Routing — routing.yaml attribute by attribute and how the intent is discovered.
  3. Tools — operation, arguments, aliases, extraction, policy, confirmation, pre-validation, and return.
  4. Workflow — when present, nodes, actions, conditions, and termination.
  5. Binding — Python/YAML/.env files involved.
  6. Diagnostics — why a specific decision occurs.

A separate section then covers Tuning-Performance.

2. Agent catalog and agent_id isolation

agent_id Name Domain Specific configuration
telecom_contas Agente Telecom Contas telecom prompt ./config/agents/telecom_contas/prompt_policy.yaml; guardrails ./config/agents/telecom_contas/guardrails.yaml; judges ./config/agents/telecom_contas/judges.yaml
retail_orders Agente Retail Pedidos retail prompt ./config/agents/retail_orders/prompt_policy.yaml; guardrails ./config/agents/retail_orders/guardrails.yaml; judges ./config/agents/retail_orders/judges.yaml

The default_agent_id is telecom_contas. Each entry's system_prefix guides the runtime so that policies, memory/checkpoints, or decisions from another agent_id are not mixed.

3. Component binding

flowchart LR
    U["GatewayRequest / message"] --> G["app/main.py"]
    G --> WF["app/workflows/agent_graph.py"]
    WF --> R["config/routing.yaml"]
    R --> A["app/agents/*_agent.py"]
    A --> RT["AgentRuntimeMixin"]
    RT --> T["config/tools.yaml"]
    T --> P["config/tool_policies.yaml"]
    T --> M["config/mcp_parameter_mapping.yaml"]
    P --> MCP["MCP Tool Router / Gateway"]
    M --> MCP
    MCP --> S["mcp/servers/telecom or retail"]
    P --> DW["workflows/*.yaml when execution=workflow"]
    DW --> WA["app/workflow_actions/*.py"]
    A --> RAG["RAG / memory / LLM"]
    A --> OS["Output Supervisor"]
    OS --> GR["Guardrails"]
    GR --> J["Judges"]
    J --> PS["Persistence / checkpoint / evidence"]

4. Rule inventory

Intent Rule Agent Priority Tools
billing_invoice_explanation Billing / Invoice Explanation billing_agent 10 consultar_fatura, consultar_pagamentos
product_services_information Products, Plan, Services, and VAS product_agent 20 consultar_plano, listar_servicos
retail_order_cancel Order Cancellation orders_agent 20 consultar_pedido, cancelar_pedido
retail_order_tracking Order Query and Tracking orders_agent 30 consultar_pedido, consultar_entrega
retail_support_exchange_return Exchange, Return, Warranty, and Retail Support support_agent 25 consultar_pedido, solicitar_troca, solicitar_devolucao

5. Rule — Billing / Invoice Explanation

Intent: billing_invoice_explanation
Domain: telecom
Agent: billing_agent
Priority: 10

What this rule means

Questions about invoices, billing, due dates, duplicate copies, disputes, and amounts.

Rule boundary

This is an informational/operational billing rule. It queries evidence; by itself it does not authorize a transactional financial action.

routing.yaml attribute by attribute

Attribute Value in this rule Role in the engine
name billing_invoice_explanation Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities.
domain telecom Logical domain. It helps constrain context, agents, and catalog interpretation.
agent billing_agent Agent that receives the turn when this intent wins.
description Questions about invoices, billing, due dates, duplicate copies, disputes, and amounts. Semantic definition used by maintainers and by the LLM fallback.
priority 10 Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence.
mcp_tools consultar_fatura
consultar_pagamentos
Capabilities initially authorized/expected for this intent.
keywords fatura
conta
cobrança
boleto
vencimento
segunda via
contestar
valor alto
invoice
Deterministic triggers evaluated before semantic fallback.
examples Minha fatura veio alta.
Quero entender uma cobrança.
Preciso da segunda via da conta.
Examples offered to the LLM classifier; they are neither regexes nor executable rules.

How this intent is found

  1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request.
  2. In deterministic matching, this intent offers keywords such as fatura, conta, cobrança, boleto, vencimento, segunda via, contestar, valor alto, invoice.
  3. In collisions, priority=10 participates in tie-breaking; lower values take precedence.
  4. If LLM fallback is used, the description and examples such as Minha fatura veio alta., Quero entender uma cobrança., Preciso da segunda via da conta. help classification.
  5. When the intent wins, state receives the route/agent and initial tool set ['consultar_fatura', 'consultar_pagamentos'].

Owning agent and Python behavior

File: app/agents/billing_agent.py. Its run() follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble messages, call the LLM, and return a state patch. This pattern comes from app/agents/runtime.py::AgentRuntimeMixin, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic.

Tools in this rule

Tool consultar_fatura

What it does: Queries summarized invoice data by msisdn/invoice_id.

Property Value
MCP server telecom
enabled True
type/operation read_only
confirmation required false
requires —
selection_keywords fatura, conta, boleto
presentation mode=renderer; renderer telecom.invoice

Required data and origin

Field Type How it is obtained Use
msisdn string canonical context customer_key Número da linha do cliente (MSISDN) usado para consultar informações de telecom.
invoice_id string canonical context contract_key Identificador da fatura que o cliente deseja consultar.

MCP aliases: customer_key → msisdn, contract_key → invoice_id, interaction_key → ura_call_id, session_key → session_id.

Conversational extraction:

  • mes_referencia: strategy month_name_pt; Extrair mês citado na mensagem. janeiro=1, fevereiro=2, março=3, abril=4, maio=5, junho=6, julho=7, agosto=8, setembro=9, outubro=10, novembro=11, dezembro=12.

What it returns: In the sample MCP it returns invoice_id, msisdn, valor_total, vencimento, status, and an itens list; the final envelope is {ok, result, metadata}.

Tool consultar_pagamentos

What it does: Queries the customer's payment history.

Property Value
MCP server telecom
enabled True
type/operation read_only
confirmation required false
requires —
selection_keywords pagamento, pagamentos

Required data and origin

Field Type How it is obtained Use
msisdn string canonical context customer_key Número da linha do cliente (MSISDN) usado para consultar informações de telecom.

MCP aliases: customer_key → msisdn, interaction_key → ura_call_id, session_key → session_id.

What it returns: Returns msisdn and pagamentos[], with date, amount, and payment status from the mock.

Workflow

This rule does not require a dedicated declarative workflow in the base template. Execution occurs through MCP/the standard runtime; transactional states may still exist for parameter collection and confirmation.

Binding between YAML and Python

  • config/routing.yaml → finds billing_invoice_explanation and selects billing_agent.
  • config/tools.yaml → describes arguments, MCP server, selection keywords, and renderer.
  • config/tool_policies.yaml → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow.
  • config/mcp_parameter_mapping.yaml → maps canonical keys and extracts fields from the message.
  • app/agents/billing_agent.py → uses AgentRuntimeMixin to execute capabilities without duplicating infrastructure.
  • app/workflows/agent_graph.py → connects the agent to the corporate graph and output controls.
  • mcp/servers/telecom_mcp_server/main.py → mock/contract implementation for tool consultar_fatura.
  • mcp/servers/telecom_mcp_server/main.py → mock/contract implementation for tool consultar_pagamentos.

Relevant .env and configuration

  • ROUTING_CONFIG_PATH=./config/routing.yaml and ENABLE_LLM_ROUTER control the routing catalog/semantic fallback.
  • ENABLE_ROUTE_STICKINESS, ROUTE_STICKINESS_*, HUMAN_HANDOFF_MESSAGE, and END_SESSION_MESSAGE control continuity/session behavior.
  • ENABLE_MCP_TOOLS, MCP_SERVERS_CONFIG_PATH, TOOLS_CONFIG_PATH, TOOL_POLICIES_PATH, MCP_PARAMETER_MAPPING_PATH, and MCP_TOOL_TIMEOUT_SECONDS control tools.
  • MCP_GATEWAY_ENABLED chooses between a dedicated MCP Gateway and direct access to configured MCP servers.
  • Logical server telecom is resolved by config/mcp_servers.yaml; in the base template it points to http://localhost:8100/mcp using the legacy HTTP contract.
  • ENABLE_INPUT_GUARDRAILS, ENABLE_OUTPUT_GUARDRAILS, ENABLE_JUDGES, and ENABLE_OUTPUT_SUPERVISOR affect the cycle before/after the agent.
  • ENABLE_CONVERSATION_SUMMARY_MEMORY and ENABLE_LONG_TERM_MEMORY may enrich prompt/context without replacing MCP evidence.
  • RAG_PROVIDER, VECTOR_STORE_PROVIDER, GRAPH_STORE_PROVIDER, RAG_TOP_K, and KBDB_* control documentary retrieval when used.

Special diagnostic — why two tools appear under the same intent

The billing intent authorizes consultar_fatura and consultar_pagamentos because billing questions may require invoice evidence or payment-history evidence. This does not mean both tools must run on every turn.

tools.yaml.selection_keywords, current text, available arguments, and runtime state help select the appropriate capability. “I need a duplicate invoice / what is my invoice amount?” should favor consultar_fatura; a specific payment question should favor consultar_pagamentos.

6. Rule — Products, Plan, Services, and VAS

Intent: product_services_information
Domain: telecom
Agent: product_agent
Priority: 20

What this rule means

Questions about plans, packages, products, services, VAS, internet, roaming, and benefits.

Rule boundary

It is used to discover plans/services/VAS and explain attributes. A product question must not be converted into a proactive offer or a transactional action.

routing.yaml attribute by attribute

Attribute Value in this rule Role in the engine
name product_services_information Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities.
domain telecom Logical domain. It helps constrain context, agents, and catalog interpretation.
agent product_agent Agent that receives the turn when this intent wins.
description Questions about plans, packages, products, services, VAS, internet, roaming, and benefits. Semantic definition used by maintainers and by the LLM fallback.
priority 20 Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence.
mcp_tools consultar_plano
listar_servicos
Capabilities initially authorized/expected for this intent.
keywords plano
serviço
pacote
internet
roaming
vas
benefício
assinatura
Deterministic triggers evaluated before semantic fallback.
examples Quais serviços estão ativos no meu plano?
Quero saber sobre meu pacote de internet.
Tenho roaming internacional?
Examples offered to the LLM classifier; they are neither regexes nor executable rules.

How this intent is found

  1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request.
  2. In deterministic matching, this intent offers keywords such as plano, serviço, pacote, internet, roaming, vas, benefício, assinatura.
  3. In collisions, priority=20 participates in tie-breaking; lower values take precedence.
  4. If LLM fallback is used, the description and examples such as Quais serviços estão ativos no meu plano?, Quero saber sobre meu pacote de internet., Tenho roaming internacional? help classification.
  5. When the intent wins, state receives the route/agent and initial tool set ['consultar_plano', 'listar_servicos'].

Owning agent and Python behavior

File: app/agents/product_agent.py. Its run() follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble messages, call the LLM, and return a state patch. This pattern comes from app/agents/runtime.py::AgentRuntimeMixin, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic.

Tools in this rule

Tool consultar_plano

What it does: Queries the active plan and commercial attributes.

Property Value
MCP server telecom
enabled True
type/operation read_only
confirmation required false
requires —
selection_keywords plano
presentation mode=renderer; renderer telecom.plan

Required data and origin

Field Type How it is obtained Use
msisdn string canonical context customer_key Número da linha do cliente (MSISDN) usado para consultar informações de telecom.
asset_id string canonical context resource_key; canonical context contract_key Identificador do plano ou ativo comercial associado ao cliente.

MCP aliases: customer_key → msisdn, resource_key → asset_id, contract_key → asset_id, session_key → session_id.

What it returns: Returns msisdn, asset_id, plan name, internet allowance, roaming attribute, and status.

Tool listar_servicos

What it does: Lists active services and additional VAS.

Property Value
MCP server telecom
enabled True
type/operation read_only
confirmation required false
requires —
selection_keywords serviços, servicos, vas

Required data and origin

Field Type How it is obtained Use
msisdn string canonical context customer_key Número da linha do cliente (MSISDN) usado para consultar informações de telecom.

MCP aliases: customer_key → msisdn, session_key → session_id.

What it returns: Returns msisdn and servicos[] containing name, status, and amount.

Workflow

This rule does not require a dedicated declarative workflow in the base template. Execution occurs through MCP/the standard runtime; transactional states may still exist for parameter collection and confirmation.

Binding between YAML and Python

  • config/routing.yaml → finds product_services_information and selects product_agent.
  • config/tools.yaml → describes arguments, MCP server, selection keywords, and renderer.
  • config/tool_policies.yaml → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow.
  • config/mcp_parameter_mapping.yaml → maps canonical keys and extracts fields from the message.
  • app/agents/product_agent.py → uses AgentRuntimeMixin to execute capabilities without duplicating infrastructure.
  • app/workflows/agent_graph.py → connects the agent to the corporate graph and output controls.
  • mcp/servers/telecom_mcp_server/main.py → mock/contract implementation for tool consultar_plano.
  • mcp/servers/telecom_mcp_server/main.py → mock/contract implementation for tool listar_servicos.

Relevant .env and configuration

  • ROUTING_CONFIG_PATH=./config/routing.yaml and ENABLE_LLM_ROUTER control the routing catalog/semantic fallback.
  • ENABLE_ROUTE_STICKINESS, ROUTE_STICKINESS_*, HUMAN_HANDOFF_MESSAGE, and END_SESSION_MESSAGE control continuity/session behavior.
  • ENABLE_MCP_TOOLS, MCP_SERVERS_CONFIG_PATH, TOOLS_CONFIG_PATH, TOOL_POLICIES_PATH, MCP_PARAMETER_MAPPING_PATH, and MCP_TOOL_TIMEOUT_SECONDS control tools.
  • MCP_GATEWAY_ENABLED chooses between a dedicated MCP Gateway and direct access to configured MCP servers.
  • Logical server telecom is resolved by config/mcp_servers.yaml; in the base template it points to http://localhost:8100/mcp using the legacy HTTP contract.
  • ENABLE_INPUT_GUARDRAILS, ENABLE_OUTPUT_GUARDRAILS, ENABLE_JUDGES, and ENABLE_OUTPUT_SUPERVISOR affect the cycle before/after the agent.
  • ENABLE_CONVERSATION_SUMMARY_MEMORY and ENABLE_LONG_TERM_MEMORY may enrich prompt/context without replacing MCP evidence.
  • RAG_PROVIDER, VECTOR_STORE_PROVIDER, GRAPH_STORE_PROVIDER, RAG_TOP_K, and KBDB_* control documentary retrieval when used.

7. Rule — Order Cancellation

Intent: retail_order_cancel
Domain: retail
Agent: orders_agent
Priority: 20

What this rule means

Explicit cancellation of an order or purchase.

Rule boundary

The intent represents the customer's desire to cancel. Execution still depends on order_id, pre-validation, and confirmation; an ineligible order is blocked before confirmation.

routing.yaml attribute by attribute

Attribute Value in this rule Role in the engine
name retail_order_cancel Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities.
domain retail Logical domain. It helps constrain context, agents, and catalog interpretation.
agent orders_agent Agent that receives the turn when this intent wins.
description Explicit cancellation of an order or purchase. Semantic definition used by maintainers and by the LLM fallback.
priority 20 Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence.
mcp_tools consultar_pedido
cancelar_pedido
Capabilities initially authorized/expected for this intent.
keywords cancelar pedido
cancelamento do pedido
cancelar a compra
cancelar compra
Deterministic triggers evaluated before semantic fallback.
examples Quero cancelar meu pedido.
Cancele o pedido.
Quero cancelar a compra.
Examples offered to the LLM classifier; they are neither regexes nor executable rules.

How this intent is found

  1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request.
  2. In deterministic matching, this intent offers keywords such as cancelar pedido, cancelamento do pedido, cancelar a compra, cancelar compra.
  3. In collisions, priority=20 participates in tie-breaking; lower values take precedence.
  4. If LLM fallback is used, the description and examples such as Quero cancelar meu pedido., Cancele o pedido., Quero cancelar a compra. help classification.
  5. When the intent wins, state receives the route/agent and initial tool set ['consultar_pedido', 'cancelar_pedido'].

Owning agent and Python behavior

File: app/agents/orders_agent.py. Its run() follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble messages, call the LLM, and return a state patch. This pattern comes from app/agents/runtime.py::AgentRuntimeMixin, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic.

Tools in this rule

Tool consultar_pedido

What it does: Queries a retail order by order_id/customer_id.

Property Value
MCP server retail
enabled True
type/operation read_only
confirmation required false
requires —
selection_keywords consultar pedido, status do pedido, pedido
presentation mode=renderer; renderer retail.order

Required data and origin

Field Type How it is obtained Use
order_id string hybrid extraction from message Identificador do pedido que o cliente deseja consultar.
customer_id string canonical context customer_key Identificador do cliente associado ao pedido de varejo.

MCP aliases: customer_key → customer_id, session_key → session_id.

Conversational extraction:

  • order_id: strategy hybrid; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem.

What it returns: Returns order_id, customer_id, status, valor_total, and itens[]. In the mock, 123 and PED-ENTREGUE are ENTREGUE; other orders are EM_TRANSPORTE.

Tool cancelar_pedido

What it does: Simulates cancellation of a retail order.

Property Value
MCP server retail
enabled True
type/operation transactional
confirmation required true
requires order_id
selection_keywords cancelar pedido, cancelamento do pedido, cancelar compra, cancelar a compra
pre-validation validar_cancelamento_pedido; fail_open=false

Required data and origin

Field Type How it is obtained Use
order_id string hybrid extraction from message Identificador do pedido que o cliente deseja cancelar.

MCP aliases: session_key → session_id.

Conversational extraction:

  • order_id: strategy hybrid; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem.

What it returns: Returns a protocol, order_id, CANCELAMENTO_SOLICITADO status, and guidance. Because it is transactional, it must only execute after parameters, pre-validation, and confirmation.

Internal tool used by the policy

Tool validar_cancelamento_pedido

What it does: Pre-validates order cancellation without executing transactional side effects.

Property Value
MCP server retail
enabled True
type/operation internal
confirmation required false
requires order_id
selection_keywords —

Required data and origin

Field Type How it is obtained Use
order_id string canonical context resource_key Identificador do pedido a ser pre-validado para cancelamento.
target_tool string state/context, parameter collection, or explicit call Nome interno da operação transacional que será pre-validada; normalmente preenchido pelo runtime e não solicitado ao usuário.

MCP aliases: resource_key → order_id.

What it returns: Returns eligible, status, order_id, a reason when blocked, and side_effect_free metadata. It is an internal/read-only tool used before confirmation.

Workflow

This rule does not require a dedicated declarative workflow in the base template. Execution occurs through MCP/the standard runtime; transactional states may still exist for parameter collection and confirmation.

Binding between YAML and Python

  • config/routing.yaml → finds retail_order_cancel and selects orders_agent.
  • config/tools.yaml → describes arguments, MCP server, selection keywords, and renderer.
  • config/tool_policies.yaml → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow.
  • config/mcp_parameter_mapping.yaml → maps canonical keys and extracts fields from the message.
  • app/agents/orders_agent.py → uses AgentRuntimeMixin to execute capabilities without duplicating infrastructure.
  • app/workflows/agent_graph.py → connects the agent to the corporate graph and output controls.
  • mcp/servers/retail_mcp_server/main.py → mock/contract implementation for tool consultar_pedido.
  • mcp/servers/retail_mcp_server/main.py → mock/contract implementation for tool cancelar_pedido.

Relevant .env and configuration

  • ROUTING_CONFIG_PATH=./config/routing.yaml and ENABLE_LLM_ROUTER control the routing catalog/semantic fallback.
  • ENABLE_ROUTE_STICKINESS, ROUTE_STICKINESS_*, HUMAN_HANDOFF_MESSAGE, and END_SESSION_MESSAGE control continuity/session behavior.
  • ENABLE_MCP_TOOLS, MCP_SERVERS_CONFIG_PATH, TOOLS_CONFIG_PATH, TOOL_POLICIES_PATH, MCP_PARAMETER_MAPPING_PATH, and MCP_TOOL_TIMEOUT_SECONDS control tools.
  • MCP_GATEWAY_ENABLED chooses between a dedicated MCP Gateway and direct access to configured MCP servers.
  • Logical server retail is resolved by config/mcp_servers.yaml; in the base template it points to http://localhost:8200/mcp using the legacy HTTP contract.
  • ENABLE_INPUT_GUARDRAILS, ENABLE_OUTPUT_GUARDRAILS, ENABLE_JUDGES, and ENABLE_OUTPUT_SUPERVISOR affect the cycle before/after the agent.
  • ENABLE_CONVERSATION_SUMMARY_MEMORY and ENABLE_LONG_TERM_MEMORY may enrich prompt/context without replacing MCP evidence.
  • RAG_PROVIDER, VECTOR_STORE_PROVIDER, GRAPH_STORE_PROVIDER, RAG_TOP_K, and KBDB_* control documentary retrieval when used.

Special diagnostic — why PED-ENTREGUE never reaches confirmation

Intent retail_order_cancel represents the customer's objective: cancel an order. After routing, the cancelar_pedido policy requires order_id, calls pre-validation tool validar_cancelamento_pedido, and only allows AWAITING_CONFIRMATION when the validator returns eligible=true.

In the sample MCP:

PED-1001
→ validar_cancelamento_pedido
→ eligible=true
→ AWAITING_CONFIRMATION
→ "yes"
→ cancelar_pedido
→ protocol CANCEL-2026-001

For:

PED-ENTREGUE
→ validar_cancelamento_pedido
→ eligible=false / NOT_ELIGIBLE
→ OUT_OF_SCOPE
→ no confirmation question
→ cancelar_pedido does not execute

This illustrates the architectural rule: intent is not operational authorization. Intent expresses what the customer wants; domain pre-validation determines whether the operation may proceed.

8. Rule — Order Query and Tracking

Intent: retail_order_tracking
Domain: retail
Agent: orders_agent
Priority: 30

What this rule means

Order, delivery, tracking, delay, and purchase-status queries.

Rule boundary

This is read-only: it queries order/delivery state and must not modify the order.

routing.yaml attribute by attribute

Attribute Value in this rule Role in the engine
name retail_order_tracking Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities.
domain retail Logical domain. It helps constrain context, agents, and catalog interpretation.
agent orders_agent Agent that receives the turn when this intent wins.
description Order, delivery, tracking, delay, and purchase-status queries. Semantic definition used by maintainers and by the LLM fallback.
priority 30 Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence.
mcp_tools consultar_pedido
consultar_entrega
Capabilities initially authorized/expected for this intent.
keywords pedido
entrega
rastreio
rastreamento
encomenda
compra
atraso
correios
Deterministic triggers evaluated before semantic fallback.
examples Meu pedido não chegou.
Quero rastrear minha entrega.
Qual é o status da minha compra?
Examples offered to the LLM classifier; they are neither regexes nor executable rules.

How this intent is found

  1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request.
  2. In deterministic matching, this intent offers keywords such as pedido, entrega, rastreio, rastreamento, encomenda, compra, atraso, correios.
  3. In collisions, priority=30 participates in tie-breaking; lower values take precedence.
  4. If LLM fallback is used, the description and examples such as Meu pedido não chegou., Quero rastrear minha entrega., Qual é o status da minha compra? help classification.
  5. When the intent wins, state receives the route/agent and initial tool set ['consultar_pedido', 'consultar_entrega'].

Owning agent and Python behavior

File: app/agents/orders_agent.py. Its run() follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble messages, call the LLM, and return a state patch. This pattern comes from app/agents/runtime.py::AgentRuntimeMixin, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic.

Tools in this rule

Tool consultar_pedido

What it does: Queries a retail order by order_id/customer_id.

Property Value
MCP server retail
enabled True
type/operation read_only
confirmation required false
requires —
selection_keywords consultar pedido, status do pedido, pedido
presentation mode=renderer; renderer retail.order

Required data and origin

Field Type How it is obtained Use
order_id string hybrid extraction from message Identificador do pedido que o cliente deseja consultar.
customer_id string canonical context customer_key Identificador do cliente associado ao pedido de varejo.

MCP aliases: customer_key → customer_id, session_key → session_id.

Conversational extraction:

  • order_id: strategy hybrid; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem.

What it returns: Returns order_id, customer_id, status, valor_total, and itens[]. In the mock, 123 and PED-ENTREGUE are ENTREGUE; other orders are EM_TRANSPORTE.

Tool consultar_entrega

What it does: Queries delivery and tracking data for an order.

Property Value
MCP server retail
enabled True
type/operation read_only
confirmation required false
requires —
selection_keywords entrega, rastreio, rastreamento, transportadora, previsão
presentation mode=renderer; renderer retail.delivery

Required data and origin

Field Type How it is obtained Use
order_id string hybrid extraction from message Identificador do pedido cuja entrega ou rastreamento será consultado.

MCP aliases: session_key → session_id.

Conversational extraction:

  • order_id: strategy hybrid; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem.

What it returns: Returns order_id, carrier, tracking code, forecast, and movement events.

Workflow

This rule does not require a dedicated declarative workflow in the base template. Execution occurs through MCP/the standard runtime; transactional states may still exist for parameter collection and confirmation.

Binding between YAML and Python

  • config/routing.yaml → finds retail_order_tracking and selects orders_agent.
  • config/tools.yaml → describes arguments, MCP server, selection keywords, and renderer.
  • config/tool_policies.yaml → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow.
  • config/mcp_parameter_mapping.yaml → maps canonical keys and extracts fields from the message.
  • app/agents/orders_agent.py → uses AgentRuntimeMixin to execute capabilities without duplicating infrastructure.
  • app/workflows/agent_graph.py → connects the agent to the corporate graph and output controls.
  • mcp/servers/retail_mcp_server/main.py → mock/contract implementation for tool consultar_pedido.
  • mcp/servers/retail_mcp_server/main.py → mock/contract implementation for tool consultar_entrega.

Relevant .env and configuration

  • ROUTING_CONFIG_PATH=./config/routing.yaml and ENABLE_LLM_ROUTER control the routing catalog/semantic fallback.
  • ENABLE_ROUTE_STICKINESS, ROUTE_STICKINESS_*, HUMAN_HANDOFF_MESSAGE, and END_SESSION_MESSAGE control continuity/session behavior.
  • ENABLE_MCP_TOOLS, MCP_SERVERS_CONFIG_PATH, TOOLS_CONFIG_PATH, TOOL_POLICIES_PATH, MCP_PARAMETER_MAPPING_PATH, and MCP_TOOL_TIMEOUT_SECONDS control tools.
  • MCP_GATEWAY_ENABLED chooses between a dedicated MCP Gateway and direct access to configured MCP servers.
  • Logical server retail is resolved by config/mcp_servers.yaml; in the base template it points to http://localhost:8200/mcp using the legacy HTTP contract.
  • ENABLE_INPUT_GUARDRAILS, ENABLE_OUTPUT_GUARDRAILS, ENABLE_JUDGES, and ENABLE_OUTPUT_SUPERVISOR affect the cycle before/after the agent.
  • ENABLE_CONVERSATION_SUMMARY_MEMORY and ENABLE_LONG_TERM_MEMORY may enrich prompt/context without replacing MCP evidence.
  • RAG_PROVIDER, VECTOR_STORE_PROVIDER, GRAPH_STORE_PROVIDER, RAG_TOP_K, and KBDB_* control documentary retrieval when used.

9. Rule — Exchange, Return, Warranty, and Retail Support

Intent: retail_support_exchange_return
Domain: retail
Agent: support_agent
Priority: 25

What this rule means

Support, exchange, return, warranty, and product-problem requests.

Rule boundary

It groups post-sale support. The intent may select exchange or return as the specific tool; transactional actions still require confirmation.

routing.yaml attribute by attribute

Attribute Value in this rule Role in the engine
name retail_support_exchange_return Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities.
domain retail Logical domain. It helps constrain context, agents, and catalog interpretation.
agent support_agent Agent that receives the turn when this intent wins.
description Support, exchange, return, warranty, and product-problem requests. Semantic definition used by maintainers and by the LLM fallback.
priority 25 Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence.
mcp_tools consultar_pedido
solicitar_troca
solicitar_devolucao
Capabilities initially authorized/expected for this intent.
keywords solicitar devolução
devolver pedido
solicitar troca
troca
devolução
devolver
garantia
defeito
produto quebrado
suporte
arrependimento
Deterministic triggers evaluated before semantic fallback.
examples Quero trocar um produto.
Meu produto veio com defeito.
Como faço uma devolução?
Examples offered to the LLM classifier; they are neither regexes nor executable rules.

How this intent is found

  1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request.
  2. In deterministic matching, this intent offers keywords such as solicitar devolução, devolver pedido, solicitar troca, troca, devolução, devolver, garantia, defeito, produto quebrado, suporte.
  3. In collisions, priority=25 participates in tie-breaking; lower values take precedence.
  4. If LLM fallback is used, the description and examples such as Quero trocar um produto., Meu produto veio com defeito., Como faço uma devolução? help classification.
  5. When the intent wins, state receives the route/agent and initial tool set ['consultar_pedido', 'solicitar_troca', 'solicitar_devolucao'].

Owning agent and Python behavior

File: app/agents/support_agent.py. Its run() follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble messages, call the LLM, and return a state patch. This pattern comes from app/agents/runtime.py::AgentRuntimeMixin, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic.

Tools in this rule

Tool consultar_pedido

What it does: Queries a retail order by order_id/customer_id.

Property Value
MCP server retail
enabled True
type/operation read_only
confirmation required false
requires —
selection_keywords consultar pedido, status do pedido, pedido
presentation mode=renderer; renderer retail.order

Required data and origin

Field Type How it is obtained Use
order_id string hybrid extraction from message Identificador do pedido que o cliente deseja consultar.
customer_id string canonical context customer_key Identificador do cliente associado ao pedido de varejo.

MCP aliases: customer_key → customer_id, session_key → session_id.

Conversational extraction:

  • order_id: strategy hybrid; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem.

What it returns: Returns order_id, customer_id, status, valor_total, and itens[]. In the mock, 123 and PED-ENTREGUE are ENTREGUE; other orders are EM_TRANSPORTE.

Tool solicitar_troca

What it does: Simulates opening an exchange request.

Property Value
MCP server retail
enabled True
type/operation transactional
confirmation required true
requires order_id, reason
selection_keywords solicitar troca, trocar, troca, defeito, quebrado

Required data and origin

Field Type How it is obtained Use
order_id string hybrid extraction from message Identificador do pedido para o qual o cliente deseja solicitar troca.
reason string default Solicitação aberta pelo atendimento conversacional. Motivo informado pelo cliente para solicitar a troca do pedido.

MCP aliases: session_key → session_id.

Conversational extraction:

  • order_id: strategy hybrid; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem.

What it returns: Returns a protocol, order_id, ABERTO status, and guidance for shipment/continuation of the exchange.

Tool solicitar_devolucao

What it does: Simulates opening a return request.

Property Value
MCP server retail
enabled True
type/operation transactional
confirmation required true
requires order_id, reason
selection_keywords solicitar devolução, solicitar devolucao, devolver pedido, devolver, devolução, devolucao, arrependimento
execution mode=workflow; workflow devolucao_pedido; version active

Required data and origin

Field Type How it is obtained Use
order_id string hybrid extraction from message Identificador do pedido para o qual o cliente deseja solicitar devolução.
reason string default Solicitação aberta pelo atendimento conversacional. Motivo informado pelo cliente para solicitar a devolução do pedido.

MCP aliases: session_key → session_id.

Conversational extraction:

  • order_id: strategy hybrid; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem.

What it returns: In direct MCP mode it returns protocol/status/guidance; in the normal template the policy selects execution.mode: workflow, so final execution goes through the deterministic devolucao_pedido workflow.

Special execution: this tool is bound to a deterministic workflow by policy; see the workflow section below.

Workflow(s) involved

Workflow devolucao_pedido.v1.yaml

Contract: name=devolucao_pedido, version=1, start=validar_pedido.

Why it is built this way: a return is a transactional multi-step action. The template separates the conversational decision from deterministic execution: it first validates the order and only registers the return when validation produces valid=true. This prevents the LLM from freely choosing the sequence of side effects.

Nodes

Node Action Input Role
validar_pedido validar_pedido order_id=$.input.order_id Initial validation point.
registrar_devolucao registrar_devolucao order_id=$.input.order_id, reason=$.input.reason Executes the return effect/registration. Uses retry=1.

Conditions and termination

From To Condition Consequence
validar_pedido registrar_devolucao {"path": "$.nodes.validar_pedido.valid", "equals": true} Advances to registrar_devolucao.
validar_pedido END {"path": "$.nodes.validar_pedido.valid", "equals": false} Terminates the workflow.
registrar_devolucao END always Terminates the workflow.

Python actions

  • app/workflow_actions/devolucao.py::validar_pedido: validates order_id and returns a contract containing valid.
  • app/workflow_actions/devolucao.py::registrar_devolucao: deterministically records the return result and produces protocol, order_id, status, and the data required for the response.

Pause/Resume

This base workflow does not contain a pause node. Collection of order_id/reason and confirmation happen earlier in the transactional runtime. Pause/resume examples are demonstrated separately in Tuning-Performance/Pause_Resume_Workflow.

Binding between YAML and Python

  • config/routing.yaml → finds retail_support_exchange_return and selects support_agent.
  • config/tools.yaml → describes arguments, MCP server, selection keywords, and renderer.
  • config/tool_policies.yaml → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow.
  • config/mcp_parameter_mapping.yaml → maps canonical keys and extracts fields from the message.
  • app/agents/support_agent.py → uses AgentRuntimeMixin to execute capabilities without duplicating infrastructure.
  • app/workflows/agent_graph.py → connects the agent to the corporate graph and output controls.
  • mcp/servers/retail_mcp_server/main.py → mock/contract implementation for tool consultar_pedido.
  • mcp/servers/retail_mcp_server/main.py → mock/contract implementation for tool solicitar_troca.
  • mcp/servers/retail_mcp_server/main.py → mock/contract implementation for tool solicitar_devolucao.

Relevant .env and configuration

  • ROUTING_CONFIG_PATH=./config/routing.yaml and ENABLE_LLM_ROUTER control the routing catalog/semantic fallback.
  • ENABLE_ROUTE_STICKINESS, ROUTE_STICKINESS_*, HUMAN_HANDOFF_MESSAGE, and END_SESSION_MESSAGE control continuity/session behavior.
  • ENABLE_MCP_TOOLS, MCP_SERVERS_CONFIG_PATH, TOOLS_CONFIG_PATH, TOOL_POLICIES_PATH, MCP_PARAMETER_MAPPING_PATH, and MCP_TOOL_TIMEOUT_SECONDS control tools.
  • MCP_GATEWAY_ENABLED chooses between a dedicated MCP Gateway and direct access to configured MCP servers.
  • Logical server retail is resolved by config/mcp_servers.yaml; in the base template it points to http://localhost:8200/mcp using the legacy HTTP contract.
  • ENABLE_INPUT_GUARDRAILS, ENABLE_OUTPUT_GUARDRAILS, ENABLE_JUDGES, and ENABLE_OUTPUT_SUPERVISOR affect the cycle before/after the agent.
  • ENABLE_CONVERSATION_SUMMARY_MEMORY and ENABLE_LONG_TERM_MEMORY may enrich prompt/context without replacing MCP evidence.
  • RAG_PROVIDER, VECTOR_STORE_PROVIDER, GRAPH_STORE_PROVIDER, RAG_TOP_K, and KBDB_* control documentary retrieval when used.

Special diagnostic — exchange and return share an intent, but not the same execution

retail_support_exchange_return groups post-sale support because the phrases have strong semantic overlap. Tool selection occurs inside the allowed set:

  • “trocar”, “troca”, “defeito”, “quebrado” → solicitar_troca;
  • “devolver”, “devolução”, “arrependimento” → solicitar_devolucao;
  • consultar_pedido may be used to obtain resource context.

Both actions are transactional and require confirmation. The main difference is that solicitar_devolucao has this policy in tool_policies.yaml:

execution:
  mode: workflow
  workflow: devolucao_pedido
  version: active

Therefore, after confirmation, a return is not merely a direct call: it enters the deterministic workflow. Exchange follows the standard transactional tool execution path.

Cross-cutting template rules and mechanisms

Tool selection within one intent

routing.yaml.mcp_tools defines the set compatible with the intent. tools.yaml.selection_keywords, available arguments, transactional state, and policies help determine which capability should execute. Two tools belonging to the same intent does not mean both must run.

Direct MCP response versus LLM

Agents call build_direct_mcp_answer(). When the result contains a sufficient deterministic renderer/contract, the runtime may respond directly and mark RAG as skipped: direct_mcp_answer.

When a direct answer is insufficient, the agent may retrieve RAG, prepare memory, and use the LLM.

prompt_policy.yaml

Defines tone and preferred vocabulary; it also registers intents/agents for prompt composition. It does not replace routing.yaml.

Configuration by agent_id

config/agents/<agent_id>/prompt_policy.yaml, guardrails.yaml, and judges.yaml allow each logical identity to be specialized. The registry lives in config/agents.yaml.

MCP transport

config/mcp_servers.yaml documents three styles:

  • http: framework legacy contract;
  • fastmcp: official MCP Streamable HTTP;
  • sse: official MCP SSE.

In the base template, telecom and retail use local http, but the registry can change without rewriting agents.

MCP Gateway

With MCP_GATEWAY_ENABLED=true, the backend delegates calls to the dedicated MCP Gateway (MCP_GATEWAY_URL). With false, it uses registry endpoints directly.

Summarized memory

ENABLE_CONVERSATION_SUMMARY_MEMORY=true allows summary + recent messages to be prepared before assembling messages. The goal is to reduce context while preserving continuity.

RAG

The template may use memory/vector/graph stores and KBDB. RAG does not replace an operational tool. ProductAgent emits detailed IC even when retrieval was attempted but produced no context.

Observability

The runtime can publish events to Langfuse, OTEL, and analytics. AgentObserver standardizes IC/NOC/GRL. The template's TelemetryObserver connects workflow events to observability infrastructure.

Presentation

app/presentation/tool_renderers.py decouples MCP payload from textual/visual response. Renderers are useful when deterministic presentation should avoid LLM cost/latency.

Workflow actions

app/workflow_actions/ contains domain effects/actions referenced by YAML. Workflow defines order/conditions; the action implements the operation.

Diagnosing an unexpected decision

  1. Check agent_id.
  2. Inspect transaction_status, next_state, paused workflow, and checkpoint.
  3. Inspect routing_decision and method (state, keyword, LLM, stickiness).
  4. Confirm intent, route, and mcp_tools.
  5. See which tool was actually selected.
  6. Compare requires with resolved_arguments/missing_parameters.
  7. Look for temporal reconciliation/contextual reentry.
  8. Inspect transaction_pre_validation.
  9. Confirm whether AWAITING_CONFIRMATION occurred.
  10. Identify direct execution versus workflow.
  11. Inspect mcp_results, transaction_evidence, RAG, and renderer.
  12. Check Output Supervisor, guardrails, and judges.
  13. Confirm persistence/pending topics at the end of the turn.

Part II — Tuning-Performance

Tuning-Performance should not be read merely as “speed optimization.” The folder acts as a catalog of isolated framework-capability scenarios, useful for benchmarking, regression, and architectural understanding.

The base template already incorporates several of these capabilities. Some directories contain a modified executable copy; others contain documentation only; Normal and Long_Term_Memory are empty in this package and therefore do not represent an additional executable variant in this version.

Tuning-Performance inventory

Scenario Content in this package Objective
Authentication README + executable template variant Cross-cutting authentication through providers/middleware and route policies.
Deterministic_Transactional_Workflow README + executable template variant Deterministic multi-step execution after confirmation.
Domain_Requested_LLM_Composition documentation/example Domain requests composition through the official LLM without creating a private LLM gateway.
Domain_Requested_RAG documentation/example Domain requests framework RAG when MCP is insufficient.
External_Guardrails_Judges README + executable template variant External guardrail/judge extensions and overhead measurement.
Long_Term_Memory documentation/example Reserved directory; the capability exists in framework/template, with no local variant in this package.
Normal documentation/example Reserved baseline; empty directory in this package.
Offline_Workflow_Regression documentation/example Opt-in deterministic fallback for offline workflow-DSL regression tests.
Pause_Resume_Workflow README + executable template variant Pause/resume by execution_id and expected_input.
Route_Stickness documentation/example Semantic continuity, handoff, session ending, and MCP policies.
Transaction_Evidence README + executable template variant Persistence/correlation of transactional operational evidence.
Transaction_Pre_Validation README + executable template variant Side-effect-free MCP validator before confirmation.
Voice_Interruption_Replay documentation/example Voice short-circuit/replay without incorrectly reexecuting the graph.
Workflow_Error_Recovery documentation/example Partial snapshot and structured error_details on workflow failure.

T1. Tuning — Authentication

Objective: Cross-cutting authentication through providers/middleware and route policies.

What this scenario demonstrates

Demonstrates authentication as a cross-cutting HTTP concern, installed before conversational processing, with provider-specific configuration and public/protected route policies.

Delta from the base template

Analyzed variant: Tuning-Performance/Authentication/agent_template_backend_authentication.

Changed files: requirements.txt, README.md, .env.example, app/main.py, app/state.py, docs/TRANSACTION_SEMANTIC_CONFIRMATION.md, config/mcp_parameter_mapping.yaml, config/tools.yaml, config/tool_policies.yaml, app/agents/product_agent.py, app/workflows/agent_graph.py.

Added files: docs/MANUAL_AUTENTICACAO.md, config/authentication.example.yaml, scripts/generate_secret_hash.py.

Engine and configuration

The variant uses install_authentication()/providers from libs/agent_framework/security and adds config/authentication.example.yaml. .env.example demonstrates:

AGENT_AUTH_MODE=basic|api_key|bearer_static|jwt|oauth2_introspection|trusted_proxy
AGENT_AUTH_PUBLIC_PATHS
AGENT_AUTH_PUBLIC_PREFIXES

In the Basic example, the credential is stored as a hash (AGENT_AUTH_BASIC_SECRET_HASH) and scripts/generate_secret_hash.py helps generate it.

Authentication is cross-cutting: it occurs at the HTTP edge/middleware before the conversational engine. It must not become a routing keyword or an agent rule.

What to validate

  • truly public routes;
  • fail-closed behavior on protected routes;
  • secret storage/rotation;
  • claims/roles/scopes per provider;
  • blocking direct pod access when using trusted_proxy;
  • observability without logging secrets/tokens.

The documentation itself marks this as a reference implementation requiring security review before production.

T2. Tuning — Deterministic_Transactional_Workflow

Objective: Deterministic multi-step execution after confirmation.

What this scenario demonstrates

Demonstrates how a confirmed transactional capability can be delegated to a deterministic workflow so the LLM does not choose the side-effect sequence.

Delta from the base template

Analyzed variant: Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend.

Changed files: .env.example, app/main.py, app/state.py, docs/TRANSACTION_SEMANTIC_CONFIRMATION.md, config/mcp_parameter_mapping.yaml, config/tools.yaml, config/tool_policies.yaml, app/agents/product_agent.py, app/agents/runtime.py, app/workflows/agent_graph.py.

Added files: tests/test_transactional_workflow_template.py.

Flow

router
→ support_agent
→ collect order_id + reason
→ AWAITING_CONFIRMATION
→ explicit confirmation
→ policy execution.mode=workflow
→ WorkflowToolExecutor
→ devolucao_pedido.active.yaml
→ devolucao_pedido.v1.yaml
→ validar_pedido
→ registrar_devolucao
→ protocol + workflow_execution_id

The main gain is not simply “having confirmation” — that already exists. The differentiator is removing post-confirmation sequence choice from the LLM.

What to measure

  • collection/confirmation time;
  • workflow latency;
  • action retries;
  • idempotency/reexecution;
  • workflow_execution_id consistency;
  • response when validar_pedido.valid=false.

T3. Tuning — Domain_Requested_LLM_Composition

Objective: Domain requests composition through the official LLM without creating a private LLM gateway.

What this scenario demonstrates

Demonstrates a domain result explicitly requesting answer composition by the framework's official LLM path.

Contract

A tool/workflow may return:

{
  "requires_llm_composition": true,
  "response_instruction": "Explain using only workflow evidence."
}

or response_instructions as a list.

AgentRuntimeMixin detects the flag recursively. When active, build_direct_mcp_answer() does not end the turn; MCP output becomes evidence for composition through the official LLM.

Architectural rule

The domain may request wording/composition, but it must not use this mechanism to decide whether a transaction occurs, invent amounts/protocols, or create a private LLM provider. Provider, profile, tracing, credentials, and costs remain framework responsibilities.

T4. Tuning — Domain_Requested_RAG

Objective: Domain requests framework RAG when MCP is insufficient.

What this scenario demonstrates

Demonstrates a domain result explicitly requesting framework RAG, including one or more retrieval queries.

Contract

{
  "requires_rag": true,
  "rag_queries": [
    "Documentary question 1",
    "Documentary question 2"
  ]
}

Flow:

tool/workflow
→ requires_rag
→ AgentRuntimeMixin
→ framework RagService
→ vector/graph store
→ LLM with MCP evidence + RAG evidence

The flag may override SKIP_RAG_WHEN_MCP_SUFFICIENT. The domain does not instantiate embeddings/vector stores; it only declares the need and queries.

T5. Tuning — External_Guardrails_Judges

Objective: External guardrail/judge extensions and overhead measurement.

What this scenario demonstrates

Demonstrates external guardrail/judge extensions and the latency/behavioral overhead they introduce.

Delta from the base template

Analyzed variant: Tuning-Performance/External_Guardrails_Judges/agent_template_backend.

Changed files: README.md, llm_profiles.yaml, .env.example, app/main.py, app/state.py, docs/TRANSACTION_SEMANTIC_CONFIRMATION.md, config/judges.yaml, config/mcp_parameter_mapping.yaml, config/tools.yaml, config/tool_policies.yaml, config/guardrails.yaml, app/agents/product_agent.py, app/workflows/agent_graph.py.

Added files: app/extensions/example_judges.py, app/extensions/__init__.py, app/extensions/example_guardrails.py.

What changes

The variant adds extensions in app/extensions/example_guardrails.py and app/extensions/example_judges.py and changes configuration to demonstrate type: external.

Correct benchmark

Compare with the extension disabled and separate:

  • p50/p95/p99;
  • allow/deny/sanitize;
  • timeout/error;
  • LLM-judge cost;
  • fail-open/fail-closed behavior;
  • transactional cases, because always_run_for_transactional may bypass sampling.

Synchronous implementations may use a worker thread; async uses the event loop. Tuning should observe provider/pool contention and must not log prompts/PII/financial payloads.

T6. Tuning — Long_Term_Memory

Objective: Reserved directory; the capability exists in framework/template, with no local variant in this package.

What this scenario demonstrates

The directory is empty in this package; the capability is documented from the base template itself.

How it works in the base template

The graph calls load_long_term_memory before routing and persist_long_term_memory near the end. The manager is created by create_long_term_memory_manager(settings, telemetry=telemetry) and injected into agents.

Main variables:

ENABLE_LONG_TERM_MEMORY
LONG_TERM_MEMORY_PROVIDER
LONG_TERM_MEMORY_SQLITE_PATH
LONG_TERM_MEMORY_TABLE
LONG_TERM_MEMORY_MAX_CONTEXT_ITEMS
LONG_TERM_MEMORY_MIN_CONFIDENCE
LONG_TERM_MEMORY_AUTO_EXTRACT
LONG_TERM_MEMORY_INJECT_CONTEXT

Do not confuse it with Transaction Evidence: LTM is semantic/durable memory; transaction evidence is structured operational fact tied to an execution/resource.

T7. Tuning — Normal

Objective: Reserved baseline; empty directory in this package.

What this scenario demonstrates

The directory is empty; the effective baseline is templates/agent_template_backend.

Baseline used in this manual

The baseline is templates/agent_template_backend. When evaluating any tuning scenario, compare against the exact same:

  • LLM/provider;
  • persistence;
  • MCP transport;
  • guardrails/judges;
  • RAG;
  • load;
  • test data.

Without a controlled baseline, latency differences cannot be attributed to the capability being studied.

T8. Tuning — Offline_Workflow_Regression

Objective: Opt-in deterministic fallback for offline workflow-DSL regression tests.

What this scenario demonstrates

Demonstrates an opt-in deterministic fallback used only for offline regression of workflow DSL behavior.

Behavior

Production still requires LangGraph. Deterministic fallback exists only when allow_deterministic_fallback=True, for builders/offline tests.

It exercises the DSL:

  • actions;
  • edges;
  • conditions;
  • pause/resume;
  • trace.

It must not be automatically selected in production, because that would hide missing/misconfigured LangGraph infrastructure.

T9. Tuning — Pause_Resume_Workflow

Objective: Pause/resume by execution_id and expected_input.

What this scenario demonstrates

Demonstrates pausing a workflow for user input and resuming the exact execution by execution_id.

Delta from the base template

Analyzed variant: Tuning-Performance/Pause_Resume_Workflow/agent_template_backend.

Changed files: README.md, docs/TRANSACTION_SEMANTIC_CONFIRMATION.md.

Added files: app/demo.py, tests/test_pause_resume.py, workflows/confirmacao.active.yaml, workflows/confirmacao.v1.yaml.

Structure

The variant adds workflows/confirmacao.v1.yaml, confirmacao.active.yaml, app/demo.py, and tests.

WorkflowRuntime.arun() starts the execution; when a node declares pause, it returns PAUSED. aresume(name, execution_id, value) resumes the same execution.

The YAML demonstrates:

  • expected_input;
  • normalization;
  • allowed values;
  • resume_from;
  • reprompt;
  • semantic_classifier;
  • contextual reentry by option.

Pause is separated from the previous action so resuming does not repeat a side effect.

T10. Tuning — Route_Stickness

Objective: Semantic continuity, handoff, session ending, and MCP policies.

What this scenario demonstrates

Demonstrates route continuity, rerouting, human handoff, and session termination without allowing stickiness to authorize tools.

Decision order

session ended? → reject/replay according to channel
route stickiness enabled?
   → CONTINUE → active agent
   → ROUTE/low confidence/error → EnterpriseRouter
   → HUMAN_HANDOFF → global node
   → END_SESSION → global node

Documented variables:

ENABLE_ROUTE_STICKINESS=true
ROUTE_STICKINESS_LLM_PROFILE=route_continuity
ROUTE_STICKINESS_CONFIDENCE_THRESHOLD=0.90
ROUTE_STICKINESS_HISTORY_TURNS=2
ROUTE_STICKINESS_MAX_TOKENS=80
HUMAN_HANDOFF_MESSAGE=...
END_SESSION_MESSAGE=...

Stickiness does not authorize tools. Even under CONTINUE, MCP calls still pass through read-only/transactional policies.

T11. Tuning — Transaction_Evidence

Objective: Persistence/correlation of transactional operational evidence.

What this scenario demonstrates

Demonstrates persistence of completed transactional evidence so later turns and judges can ground references to prior operations.

Delta from the base template

Analyzed variant: Tuning-Performance/Transaction_Evidence/agent_template_backend.

Changed files: .env.example, app/main.py, app/state.py, docs/TRANSACTION_SEMANTIC_CONFIRMATION.md, config/mcp_parameter_mapping.yaml, config/tools.yaml, config/tool_policies.yaml, app/agents/product_agent.py, app/workflows/agent_graph.py.

Added files: none.

Problem solved

A transaction may occur in one turn and be referenced later. Without persisted evidence, groundedness may consider a prior cancellation/protocol unsupported.

The runtime writes transaction_evidence and correlates relevant items into relevant_transaction_evidence.

Example:

cancelar_pedido(PED-1001)
→ COMPLETED
→ protocol
→ transaction_evidence
...
"show me my order"
→ consultar_pedido
→ relevant_transaction_evidence from cancellation
→ response + judges receive the same evidence

Transaction Evidence is operational, not semantic memory.

T12. Tuning — Transaction_Pre_Validation

Objective: Side-effect-free MCP validator before confirmation.

What this scenario demonstrates

Demonstrates side-effect-free validation before the user is asked to confirm a sensitive transaction.

Delta from the base template

Analyzed variant: Tuning-Performance/Transaction_Pre_Validation/agent_template_backend.

Changed files: .env.example, docs/TRANSACTION_SEMANTIC_CONFIRMATION.md, app/agents/product_agent.py, app/workflows/agent_graph.py.

Added files: none.

Flow

complete parameters
→ validar_cancelamento_pedido
→ eligible?
   ├─ false → OUT_OF_SCOPE / terminal / clear latch
   └─ true  → AWAITING_CONFIRMATION
               ↓
              yes
               ↓
          cancelar_pedido

fail_open=false is appropriate for a sensitive operation. Rejection does not become transaction_evidence, because the business operation did not occur.

Expected events include:

IC.TRANSACTION_PREVALIDATION_REQUESTED
IC.TRANSACTION_PREVALIDATION_PASSED
IC.TRANSACTION_PREVALIDATION_REJECTED
IC.TRANSACTION_CONFIRMATION_REQUIRED

T13. Tuning — Voice_Interruption_Replay

Objective: Voice short-circuit/replay without incorrectly reexecuting the graph.

What this scenario demonstrates

Demonstrates voice replay/short-circuit decisions that avoid unnecessary graph and tool execution.

Framework-native order

  1. ended session → terminal replay;
  2. idle nudge → replay last real utterance;
  3. non-interruptible speech → literal replay;
  4. interruptible speech with context → processing_interruption_classifier;
  5. insufficient context → normal processing.

On short-circuit, metadata reports replay=true, framework_short_circuit=true and avoids LangGraph/tools/guardrails. In classifier cases, only the lightweight classification LLM may be called.

T14. Tuning — Workflow_Error_Recovery

Objective: Partial snapshot and structured error_details on workflow failure.

What this scenario demonstrates

Demonstrates preserving partial output/trace and structured provider error details when a workflow fails.

Failure contract

WorkflowRunResult preserves:

  • output: nodes completed before failure;
  • trace: partial path;
  • error: message;
  • error_details: when available, status_code, body, attempts.

This keeps the framework generic while allowing the domain to interpret provider details without coupling the workflow engine to a specific integration.

Part III — maintenance file map

Base template

Area File
API / session / SSE / entry templates/agent_template_backend/app/main.py
State app/state.py
Graph app/workflows/agent_graph.py
Common agent runtime app/agents/runtime.py
Billing app/agents/billing_agent.py
Products app/agents/product_agent.py
Orders app/agents/orders_agent.py
Support app/agents/support_agent.py
Routing config/routing.yaml
Agents registry config/agents.yaml
Tools config/tools.yaml
Policies config/tool_policies.yaml
MCP parameters config/mcp_parameter_mapping.yaml
MCP servers config/mcp_servers.yaml
Guardrails config/guardrails.yaml
Judges config/judges.yaml
Prompt policy config/prompt_policy.yaml
Return workflow workflows/devolucao_pedido.v1.yaml
Workflow active pointer workflows/devolucao_pedido.active.yaml
Return actions app/workflow_actions/devolucao.py
Renderers app/presentation/tool_renderers.py
Observability app/observability/telemetry_observer.py
Framework runtime libs/agent_framework/src/agent_framework/runtime/agent_runtime.py
Router libs/agent_framework/src/agent_framework/routing/enterprise_router.py
Multi-intent libs/agent_framework/src/agent_framework/routing/multi_intent.py
Pending topics libs/agent_framework/src/agent_framework/routing/pending_topics.py
Parameters/reconciliation libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py
Workflow runtime libs/agent_framework/src/agent_framework/workflows/

How to create a new rule without hardcoding the core

  1. Define the intent in config/routing.yaml.
  2. Point it to an existing agent or create one under app/agents/.
  3. Register the agent in the graph only if it is new.
  4. Declare capabilities in config/tools.yaml.
  5. Declare confirmation/pre-validation/workflow in config/tool_policies.yaml.
  6. Configure aliases/extract/defaults in config/mcp_parameter_mapping.yaml.
  7. Implement the tool in the MCP Server, not in the router.
  8. For multi-step orchestration, create workflow YAML and Python actions.
  9. Add guardrails/judges only for cross-cutting/quality concerns; do not use guardrails as routers.
  10. Test state, collection, confirmation, intent shift, retry, idempotency, and groundedness.
  11. If the capability needs advanced behavior, consult the Tuning-Performance scenarios before duplicating infrastructure in the agent.