new feature: Multi-Intent

This commit is contained in:
2026-09-10 22:55:58 -03:00
parent 82d96f2dbf
commit a9bbad22a5
250 changed files with 648 additions and 46 deletions

View File

@@ -569,6 +569,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -576,6 +577,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -644,6 +649,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -569,6 +569,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -576,6 +577,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -644,6 +649,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -567,6 +567,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -574,6 +575,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -642,6 +647,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -569,6 +569,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -576,6 +577,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -644,6 +649,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -567,6 +567,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -574,6 +575,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -642,6 +647,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -567,6 +567,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -574,6 +575,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -642,6 +647,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -567,6 +567,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -574,6 +575,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -642,6 +647,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -567,6 +567,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -574,6 +575,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -642,6 +647,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -569,6 +569,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -576,6 +577,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -644,6 +649,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -569,6 +569,7 @@ class AgentWorkflow:
"final_answer": candidate, "final_answer": candidate,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"output_guardrails_already_applied": False, "output_guardrails_already_applied": False,
"supervisor_action": "disabled", "supervisor_action": "disabled",
"supervisor_attempt": int(state.get("supervisor_attempt", 0)), "supervisor_attempt": int(state.get("supervisor_attempt", 0)),
@@ -576,6 +577,10 @@ class AgentWorkflow:
context = { context = {
**(state.get("context") or {}), **(state.get("context") or {}),
"evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),
"tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),
"tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),
"mcp_results": drained.mcp_results,
"tenant_id": state.get("tenant_id"), "tenant_id": state.get("tenant_id"),
"agent_id": state.get("agent_id"), "agent_id": state.get("agent_id"),
"session_id": state.get("conversation_key") or state.get("session_id"), "session_id": state.get("conversation_key") or state.get("session_id"),
@@ -644,6 +649,7 @@ class AgentWorkflow:
"output_guardrails_already_applied": True, "output_guardrails_already_applied": True,
"pending_topics": drained.pending_topics, "pending_topics": drained.pending_topics,
"handled_topics": drained.handled_topics, "handled_topics": drained.handled_topics,
"mcp_results": drained.mcp_results,
"guardrail_decisions": state.get("guardrail_decisions", []) "guardrail_decisions": state.get("guardrail_decisions", [])
+ [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])],
} }

View File

@@ -2,9 +2,8 @@
`MultiIntentPlanner` recognizes independent requests in one utterance and `MultiIntentPlanner` recognizes independent requests in one utterance and
builds a plan constrained to the intents, agents, and tools declared in builds a plan constrained to the intents, agents, and tools declared in
`config/routing.yaml`. It does not execute operations or let the LLM invent a `config/routing.yaml`. It does not execute operations: the router selects the
sequence: the router selects the primary operation and the domain workflow primary operation and the domain workflow continues to own the transaction.
continues to own the transaction.
## Configuration and execution ## Configuration and execution
@@ -12,12 +11,21 @@ No additional configuration is required. The planner uses the intents already
declared in `routing.yaml`, selects the single transactional operation from declared in `routing.yaml`, selects the single transactional operation from
`tool_policies.yaml`, and persists the remaining requests as `pending_topics`. `tool_policies.yaml`, and persists the remaining requests as `pending_topics`.
When `ENABLE_LLM_ROUTER=true`, a compound message whose deterministic plan is
missing or incomplete is sent to a structured multi-intent classifier. The LLM
may return only configured intent names and source fragments. Agent, domain,
and tool ownership are always hydrated from `routing.yaml`; unknown intents,
low confidence, and invalid JSON are rejected. The default confidence threshold
is `0.65` and can be overridden with
`multi_intent.llm_confidence_threshold`.
Known read-only topics execute through their own agent. A second mutation stays Known read-only topics execute through their own agent. A second mutation stays
pending for its own confirmation, while an unknown clause becomes off-context. pending for its own confirmation, while an unknown clause becomes off-context.
The router resolves clauses from registered intent keywords and routes the The router first resolves clauses from registered intent keywords, then uses the
transactional operation first. The graph drains read-only pending topics before semantic fallback only for an absent or incomplete compound plan, and routes
output supervision. During an open transaction, the transactional operation first. The graph drains read-only pending topics
before output supervision. During an open transaction,
`yes, and send me the invoice` confirms the transaction and records the `yes, and send me the invoice` confirms the transaction and records the
secondary request instead of causing an intent shift. secondary request instead of causing an intent shift.

View File

@@ -2,9 +2,8 @@
O `MultiIntentPlanner` reconhece solicitações independentes na mesma mensagem e O `MultiIntentPlanner` reconhece solicitações independentes na mesma mensagem e
cria um plano limitado às intents, agents e tools declarados em cria um plano limitado às intents, agents e tools declarados em
`config/routing.yaml`. O planejador não executa operações nem permite que o LLM `config/routing.yaml`. O planejador não executa operações. O roteador escolhe a
invente uma sequência: o roteador escolhe a operação primária e o workflow do operação primária e o workflow do domínio continua responsável pela transação.
domínio continua responsável pela transação.
## Configuração ## Configuração
@@ -12,6 +11,13 @@ Não existe configuração adicional. O planejador usa as intents do `routing.ya
e lê `tool_policies.yaml` para priorizar automaticamente a única operação e lê `tool_policies.yaml` para priorizar automaticamente a única operação
transacional. Pedidos secundários são persistidos em `pending_topics`. transacional. Pedidos secundários são persistidos em `pending_topics`.
Quando `ENABLE_LLM_ROUTER=true`, mensagens compostas que não produzam um plano
determinístico completo passam por um classificador multi-intent estruturado. O
resultado do LLM só informa nomes de intents e trechos da mensagem. Agent,
domínio e tools são sempre recuperados do `routing.yaml`; intent inexistente,
baixa confiança ou JSON inválido são rejeitados. O limite padrão de confiança é
`0.65` e pode ser sobrescrito por `multi_intent.llm_confidence_threshold`.
- intent conhecida e read-only: executada pelo agent correspondente; - intent conhecida e read-only: executada pelo agent correspondente;
- intent conhecida e transacional: mantida pendente para confirmação própria; - intent conhecida e transacional: mantida pendente para confirmação própria;
- trecho sem capability correspondente: respondido como `off_context`. - trecho sem capability correspondente: respondido como `off_context`.
@@ -24,10 +30,12 @@ workflow transacional coordenador.
1. O `EnterpriseRouter` separa a entrada em cláusulas e resolve cada uma pelas 1. O `EnterpriseRouter` separa a entrada em cláusulas e resolve cada uma pelas
keywords das intents cadastradas. keywords das intents cadastradas.
2. `tool_policies.yaml` identifica a operação transacional e a torna primária. 2. Se o plano estiver ausente ou contiver trecho provisoriamente fora de escopo,
3. A primeira operação é roteada normalmente para seu agent/workflow. o classificador LLM tenta reconhecer semanticamente as intents componentes.
4. O `agent_graph` compõe as mensagens públicas antes do supervisor de saída. 3. `tool_policies.yaml` identifica a operação transacional e a torna primária.
5. Durante uma confirmação, uma frase como `sim e me manda a segunda via` 4. A primeira operação é roteada normalmente para seu agent/workflow.
5. O `agent_graph` compõe as mensagens públicas antes do supervisor de saída.
6. Durante uma confirmação, uma frase como `sim e me manda a segunda via`
confirma a transação aberta e registra a solicitação secundária, sem causar confirma a transação aberta e registra a solicitação secundária, sem causar
troca indevida de intent. troca indevida de intent.

Some files were not shown because too many files have changed in this diff Show More