From 3f884d028aa933287fa85ee47c502d508e2da6fc Mon Sep 17 00:00:00 2001 From: "cristiano.hoshikawa" Date: Thu, 10 Sep 2026 22:55:50 -0300 Subject: [PATCH] new feature: Multi-Intent --- .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + docs/features/en/16_multi_intent_planning.md | 20 ++- .../pt-BR/16_multi_intent_planning.md | 22 ++- .../__pycache__/__init__.cpython-313.pyc | Bin 413 -> 413 bytes .../__pycache__/extensions.cpython-313.pyc | Bin 2141 -> 2141 bytes .../__pycache__/idempotency.cpython-313.pyc | Bin 8914 -> 8914 bytes .../__pycache__/observer.cpython-313.pyc | Bin 17557 -> 17557 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 549 -> 549 bytes .../composite_publisher.cpython-313.pyc | Bin 2504 -> 2504 bytes .../__pycache__/event_builder.cpython-313.pyc | Bin 1262 -> 1262 bytes .../__pycache__/factory.cpython-313.pyc | Bin 3998 -> 3998 bytes .../__pycache__/publisher.cpython-313.pyc | Bin 1874 -> 1874 bytes .../tim_payload_mapper.cpython-313.pyc | Bin 9288 -> 9288 bytes .../__pycache__/tim_sequence.cpython-313.pyc | Bin 17563 -> 17563 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 516 -> 516 bytes .../__pycache__/kafka.cpython-313.pyc | Bin 1814 -> 1814 bytes .../__pycache__/langfuse.cpython-313.pyc | Bin 23174 -> 23174 bytes .../__pycache__/oci_streaming.cpython-313.pyc | Bin 1823 -> 1823 bytes .../__pycache__/pubsub.cpython-313.pyc | Bin 7442 -> 7442 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 405 -> 405 bytes .../usage_repository.cpython-313.pyc | Bin 15688 -> 15688 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 215 -> 215 bytes .../cache/__pycache__/cache.cpython-313.pyc | Bin 16525 -> 16525 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 218 -> 218 bytes .../__pycache__/adapters.cpython-313.pyc | Bin 4174 -> 4174 bytes .../channels/__pycache__/base.cpython-313.pyc | Bin 1798 -> 1798 bytes .../__pycache__/gateway.cpython-313.pyc | Bin 5773 -> 5773 bytes .../__pycache__/interruption.cpython-313.pyc | Bin 6458 -> 6458 bytes .../__pycache__/transcription.cpython-313.pyc | Bin 1431 -> 1431 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 925 -> 925 bytes .../checkpoint_repository.cpython-313.pyc | Bin 27165 -> 27165 bytes .../langgraph_saver.cpython-313.pyc | Bin 33267 -> 33267 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 216 -> 216 bytes .../agent_registry.cpython-313.pyc | Bin 6949 -> 6949 bytes .../__pycache__/settings.cpython-313.pyc | Bin 13791 -> 13791 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 308 -> 308 bytes .../mcp_gateway_client.cpython-313.pyc | Bin 3334 -> 3334 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1503 -> 1503 bytes .../__pycache__/base.cpython-313.pyc | Bin 1377 -> 1377 bytes .../__pycache__/config_loader.cpython-313.pyc | Bin 9162 -> 9162 bytes .../__pycache__/custom_rails.cpython-313.pyc | Bin 4406 -> 4406 bytes .../framework_llm_client.cpython-313.pyc | Bin 19675 -> 19675 bytes .../__pycache__/llm_rails.cpython-313.pyc | Bin 5925 -> 5925 bytes .../output_supervisor.cpython-313.pyc | Bin 24308 -> 24308 bytes .../parallel_executor.cpython-313.pyc | Bin 21864 -> 21864 bytes .../__pycache__/pipeline.cpython-313.pyc | Bin 10891 -> 10891 bytes .../__pycache__/rail_action.cpython-313.pyc | Bin 656 -> 656 bytes .../__pycache__/rail_decision.cpython-313.pyc | Bin 1607 -> 1607 bytes .../__pycache__/rail_result.cpython-313.pyc | Bin 1006 -> 1006 bytes .../__pycache__/rails.cpython-313.pyc | Bin 43326 -> 43326 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 2996 -> 2996 bytes .../__pycache__/_compat.cpython-313.pyc | Bin 2447 -> 2447 bytes .../contestation_validation.cpython-313.pyc | Bin 2179 -> 2179 bytes .../__pycache__/contracts.cpython-313.pyc | Bin 6903 -> 6903 bytes .../__pycache__/input_size.cpython-313.pyc | Bin 3651 -> 3651 bytes .../__pycache__/llm_adapter.cpython-313.pyc | Bin 3801 -> 3801 bytes .../__pycache__/llm_client.cpython-313.pyc | Bin 7456 -> 7456 bytes .../__pycache__/llm_rails.cpython-313.pyc | Bin 8896 -> 8896 bytes .../output_sanitization.cpython-313.pyc | Bin 13912 -> 13912 bytes .../__pycache__/pipeline.cpython-313.pyc | Bin 12663 -> 12663 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 475 -> 475 bytes .../__pycache__/_context.cpython-313.pyc | Bin 5873 -> 5873 bytes .../ausencia_oferta_proativa.cpython-313.pyc | Bin 12207 -> 12207 bytes .../__pycache__/coerencia.cpython-313.pyc | Bin 4159 -> 4159 bytes .../__pycache__/dlex_in.cpython-313.pyc | Bin 1306 -> 1306 bytes .../__pycache__/dlex_out.cpython-313.pyc | Bin 1817 -> 1817 bytes .../__pycache__/fallback.cpython-313.pyc | Bin 17654 -> 17654 bytes .../__pycache__/fraseologia.cpython-313.pyc | Bin 7635 -> 7635 bytes .../__pycache__/out_of_scope.cpython-313.pyc | Bin 17495 -> 17495 bytes .../prompts/__pycache__/pinj.cpython-313.pyc | Bin 8426 -> 8426 bytes .../__pycache__/ragsec.cpython-313.pyc | Bin 1122 -> 1122 bytes .../__pycache__/revprec.cpython-313.pyc | Bin 3152 -> 3152 bytes .../prompts/__pycache__/tox.cpython-313.pyc | Bin 646 -> 646 bytes .../toxicidade_output.cpython-313.pyc | Bin 930 -> 930 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1665 -> 1665 bytes .../rails/__pycache__/alcada.cpython-313.pyc | Bin 5001 -> 5001 bytes .../rails/__pycache__/anatel.cpython-313.pyc | Bin 9150 -> 9150 bytes .../__pycache__/confirmation.cpython-313.pyc | Bin 11044 -> 11044 bytes .../rails/__pycache__/dlex_in.cpython-313.pyc | Bin 3281 -> 3281 bytes .../__pycache__/dlex_out.cpython-313.pyc | Bin 3333 -> 3333 bytes .../rails/__pycache__/ragsec.cpython-313.pyc | Bin 5464 -> 5464 bytes .../rails/__pycache__/revprec.cpython-313.pyc | Bin 5472 -> 5472 bytes .../rails/__pycache__/tox.cpython-313.pyc | Bin 8295 -> 8295 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 535 -> 535 bytes .../rules/__pycache__/alcada.cpython-313.pyc | Bin 1883 -> 1883 bytes .../__pycache__/pinj_patterns.cpython-313.pyc | Bin 3732 -> 3732 bytes .../__pycache__/tox_blocklist.cpython-313.pyc | Bin 1508 -> 1508 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 410 -> 410 bytes .../__pycache__/mcp_mapper.cpython-313.pyc | Bin 4694 -> 4694 bytes .../__pycache__/models.cpython-313.pyc | Bin 3146 -> 3146 bytes .../__pycache__/resolver.cpython-313.pyc | Bin 4715 -> 4715 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 620 -> 620 bytes .../judges/__pycache__/judge.cpython-313.pyc | Bin 41127 -> 43986 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 227 -> 227 bytes .../__pycache__/llm_client.cpython-313.pyc | Bin 5406 -> 5406 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 235 -> 235 bytes .../prompts/__pycache__/aluc.cpython-313.pyc | Bin 6531 -> 6531 bytes .../prompts/__pycache__/csi.cpython-313.pyc | Bin 1334 -> 1334 bytes .../__pycache__/fallback.cpython-313.pyc | Bin 8037 -> 8037 bytes .../prompts/__pycache__/rqlt.cpython-313.pyc | Bin 1167 -> 1167 bytes .../prompts/__pycache__/vctn.cpython-313.pyc | Bin 628 -> 628 bytes .../src/agent_framework/judges/judge.py | 53 +++++- .../llm/__pycache__/__init__.cpython-313.pyc | Bin 478 -> 478 bytes .../llm/__pycache__/base.cpython-313.pyc | Bin 1625 -> 1625 bytes .../profile_resolver.cpython-313.pyc | Bin 9324 -> 9324 bytes .../llm/__pycache__/providers.cpython-313.pyc | Bin 46980 -> 46980 bytes .../structured_output.cpython-313.pyc | Bin 7461 -> 7461 bytes .../llm/__pycache__/types.cpython-313.pyc | Bin 1276 -> 1276 bytes .../mcp/__pycache__/__init__.cpython-313.pyc | Bin 475 -> 475 bytes .../mcp/__pycache__/client.cpython-313.pyc | Bin 18428 -> 18428 bytes .../mcp/__pycache__/models.cpython-313.pyc | Bin 2138 -> 2138 bytes .../mcp/__pycache__/registry.cpython-313.pyc | Bin 4742 -> 4742 bytes .../__pycache__/tool_policy.cpython-313.pyc | Bin 5687 -> 5687 bytes .../__pycache__/tool_router.cpython-313.pyc | Bin 14191 -> 14191 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1137 -> 1137 bytes .../long_term_extractor.cpython-313.pyc | Bin 2515 -> 2515 bytes .../long_term_memory.cpython-313.pyc | Bin 6841 -> 6841 bytes .../long_term_models.cpython-313.pyc | Bin 1750 -> 1750 bytes .../long_term_store.cpython-313.pyc | Bin 29188 -> 29188 bytes .../message_history.cpython-313.pyc | Bin 8361 -> 8361 bytes .../summary_memory.cpython-313.pyc | Bin 12512 -> 12512 bytes .../__pycache__/summary_store.cpython-313.pyc | Bin 9522 -> 9522 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 216 -> 216 bytes .../__pycache__/identity.cpython-313.pyc | Bin 3467 -> 3467 bytes .../__pycache__/session.cpython-313.pyc | Bin 2710 -> 2710 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1396 -> 1396 bytes .../__pycache__/code_mapper.cpython-313.pyc | Bin 21449 -> 21449 bytes .../__pycache__/context.cpython-313.pyc | Bin 7388 -> 7388 bytes .../__pycache__/event_bus.cpython-313.pyc | Bin 3634 -> 3634 bytes .../guardrail_events.cpython-313.pyc | Bin 2052 -> 2052 bytes .../__pycache__/ic_events.cpython-313.pyc | Bin 627 -> 627 bytes .../__pycache__/judge_events.cpython-313.pyc | Bin 1412 -> 1412 bytes .../langgraph_telemetry.cpython-313.pyc | Bin 4965 -> 4965 bytes .../__pycache__/llm_advisors.cpython-313.pyc | Bin 2939 -> 2939 bytes .../__pycache__/noc_contract.cpython-313.pyc | Bin 5076 -> 5076 bytes .../__pycache__/noc_otel.cpython-313.pyc | Bin 6323 -> 6323 bytes .../__pycache__/observer.cpython-313.pyc | Bin 5106 -> 5106 bytes .../__pycache__/otel.cpython-313.pyc | Bin 3413 -> 3413 bytes .../streaming_events.cpython-313.pyc | Bin 1836 -> 1836 bytes .../__pycache__/telemetry.cpython-313.pyc | Bin 52429 -> 52429 bytes .../__pycache__/token_cost.cpython-313.pyc | Bin 8692 -> 8692 bytes .../workflow_events.cpython-313.pyc | Bin 3331 -> 3331 bytes .../oci/__pycache__/__init__.cpython-313.pyc | Bin 213 -> 213 bytes .../oci/__pycache__/auth.cpython-313.pyc | Bin 3245 -> 3245 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 221 -> 221 bytes .../__pycache__/oracle_store.cpython-313.pyc | Bin 45933 -> 45933 bytes .../__pycache__/sqlite_store.cpython-313.pyc | Bin 15020 -> 15020 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 456 -> 456 bytes .../__pycache__/renderers.cpython-313.pyc | Bin 4319 -> 4319 bytes .../rag/__pycache__/__init__.cpython-313.pyc | Bin 711 -> 711 bytes .../embedding_provider.cpython-313.pyc | Bin 6518 -> 6518 bytes .../__pycache__/graph_store.cpython-313.pyc | Bin 5529 -> 5529 bytes .../rag/__pycache__/ingest.cpython-313.pyc | Bin 12582 -> 12582 bytes .../__pycache__/kbdb_service.cpython-313.pyc | Bin 10013 -> 10013 bytes .../__pycache__/rag_service.cpython-313.pyc | Bin 10899 -> 10899 bytes .../__pycache__/vector_store.cpython-313.pyc | Bin 18657 -> 18657 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 222 -> 222 bytes .../session_repository.cpython-313.pyc | Bin 8591 -> 8591 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 649 -> 649 bytes .../__pycache__/config_loader.cpython-313.pyc | Bin 2691 -> 2691 bytes .../__pycache__/continuity.cpython-313.pyc | Bin 15935 -> 15935 bytes .../enterprise_router.cpython-313.pyc | Bin 64784 -> 69460 bytes .../__pycache__/models.cpython-313.pyc | Bin 2448 -> 2448 bytes .../__pycache__/multi_intent.cpython-313.pyc | Bin 13086 -> 19979 bytes .../pending_topics.cpython-313.pyc | Bin 5570 -> 5814 bytes .../routing/enterprise_router.py | 116 ++++++++++++- .../agent_framework/routing/multi_intent.py | 153 +++++++++++++++--- .../agent_framework/routing/pending_topics.py | 13 +- .../__pycache__/__init__.cpython-313.pyc | Bin 350 -> 350 bytes .../__pycache__/agent_runtime.cpython-313.pyc | Bin 198240 -> 198240 bytes .../transaction_parameters.cpython-313.pyc | Bin 19585 -> 19585 bytes .../sse/__pycache__/__init__.cpython-313.pyc | Bin 213 -> 213 bytes .../sse/__pycache__/events.cpython-313.pyc | Bin 9589 -> 9589 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 220 -> 220 bytes .../__pycache__/supervisor.cpython-313.pyc | Bin 4945 -> 4945 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 880 -> 880 bytes .../__pycache__/graph.cpython-313.pyc | Bin 1417 -> 1417 bytes .../input_contract.cpython-313.pyc | Bin 8792 -> 8792 bytes .../__pycache__/models.cpython-313.pyc | Bin 7671 -> 7671 bytes .../__pycache__/registry.cpython-313.pyc | Bin 2363 -> 2363 bytes .../__pycache__/repository.cpython-313.pyc | Bin 2716 -> 2716 bytes .../__pycache__/runtime.cpython-313.pyc | Bin 36154 -> 36154 bytes .../__pycache__/tool_executor.cpython-313.pyc | Bin 1968 -> 1968 bytes scripts/sync_pending_topics_to_tuning.py | 29 ++++ .../app/workflows/agent_graph.py | 6 + .../app/workflows/agent_graph.py | 6 + tests/unit/test_multi_intent_planner.py | 117 ++++++++++++++ tests/unit/test_pending_topics_isolation.py | 12 +- tests/unit/test_tuning_pending_topics_sync.py | 4 + 198 files changed, 566 insertions(+), 45 deletions(-) diff --git a/Tuning-Performance/Authentication/agent_template_backend_authentication/app/workflows/agent_graph.py b/Tuning-Performance/Authentication/agent_template_backend_authentication/app/workflows/agent_graph.py index bb2d550a..d45cb7b9 100644 --- a/Tuning-Performance/Authentication/agent_template_backend_authentication/app/workflows/agent_graph.py +++ b/Tuning-Performance/Authentication/agent_template_backend_authentication/app/workflows/agent_graph.py @@ -569,6 +569,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -576,6 +577,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -644,6 +649,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend/app/workflows/agent_graph.py b/Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend/app/workflows/agent_graph.py index bb2d550a..d45cb7b9 100644 --- a/Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend/app/workflows/agent_graph.py +++ b/Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend/app/workflows/agent_graph.py @@ -569,6 +569,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -576,6 +577,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -644,6 +649,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/Tuning-Performance/External_Guardrails_Judges/agent_template_backend/app/workflows/agent_graph.py b/Tuning-Performance/External_Guardrails_Judges/agent_template_backend/app/workflows/agent_graph.py index 5c5f9a28..1f139537 100644 --- a/Tuning-Performance/External_Guardrails_Judges/agent_template_backend/app/workflows/agent_graph.py +++ b/Tuning-Performance/External_Guardrails_Judges/agent_template_backend/app/workflows/agent_graph.py @@ -567,6 +567,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -574,6 +575,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -642,6 +647,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/app/workflows/agent_graph.py b/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/app/workflows/agent_graph.py index bb2d550a..d45cb7b9 100644 --- a/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/app/workflows/agent_graph.py +++ b/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/app/workflows/agent_graph.py @@ -569,6 +569,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -576,6 +577,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -644,6 +649,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/Tuning-Performance/Normal/templates/agent_template_backend/app/workflows/agent_graph.py b/Tuning-Performance/Normal/templates/agent_template_backend/app/workflows/agent_graph.py index 5c5f9a28..1f139537 100644 --- a/Tuning-Performance/Normal/templates/agent_template_backend/app/workflows/agent_graph.py +++ b/Tuning-Performance/Normal/templates/agent_template_backend/app/workflows/agent_graph.py @@ -567,6 +567,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -574,6 +575,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -642,6 +647,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/Tuning-Performance/Normal/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py b/Tuning-Performance/Normal/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py index 5c5f9a28..1f139537 100644 --- a/Tuning-Performance/Normal/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py +++ b/Tuning-Performance/Normal/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py @@ -567,6 +567,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -574,6 +575,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -642,6 +647,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/Tuning-Performance/Route_Stickness/templates/agent_template_backend/app/workflows/agent_graph.py b/Tuning-Performance/Route_Stickness/templates/agent_template_backend/app/workflows/agent_graph.py index 5c5f9a28..1f139537 100644 --- a/Tuning-Performance/Route_Stickness/templates/agent_template_backend/app/workflows/agent_graph.py +++ b/Tuning-Performance/Route_Stickness/templates/agent_template_backend/app/workflows/agent_graph.py @@ -567,6 +567,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -574,6 +575,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -642,6 +647,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/Tuning-Performance/Route_Stickness/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py b/Tuning-Performance/Route_Stickness/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py index 5c5f9a28..1f139537 100644 --- a/Tuning-Performance/Route_Stickness/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py +++ b/Tuning-Performance/Route_Stickness/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py @@ -567,6 +567,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -574,6 +575,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -642,6 +647,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/Tuning-Performance/Transaction_Evidence/agent_template_backend/app/workflows/agent_graph.py b/Tuning-Performance/Transaction_Evidence/agent_template_backend/app/workflows/agent_graph.py index b950fa4e..f700f35d 100644 --- a/Tuning-Performance/Transaction_Evidence/agent_template_backend/app/workflows/agent_graph.py +++ b/Tuning-Performance/Transaction_Evidence/agent_template_backend/app/workflows/agent_graph.py @@ -569,6 +569,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -576,6 +577,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -644,6 +649,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/Tuning-Performance/Transaction_Pre_Validation/agent_template_backend/app/workflows/agent_graph.py b/Tuning-Performance/Transaction_Pre_Validation/agent_template_backend/app/workflows/agent_graph.py index b950fa4e..f700f35d 100644 --- a/Tuning-Performance/Transaction_Pre_Validation/agent_template_backend/app/workflows/agent_graph.py +++ b/Tuning-Performance/Transaction_Pre_Validation/agent_template_backend/app/workflows/agent_graph.py @@ -569,6 +569,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -576,6 +577,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -644,6 +649,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/docs/features/en/16_multi_intent_planning.md b/docs/features/en/16_multi_intent_planning.md index fbc3c122..a5ebef5c 100644 --- a/docs/features/en/16_multi_intent_planning.md +++ b/docs/features/en/16_multi_intent_planning.md @@ -2,9 +2,8 @@ `MultiIntentPlanner` recognizes independent requests in one utterance and 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 -sequence: the router selects the primary operation and the domain workflow -continues to own the transaction. +`config/routing.yaml`. It does not execute operations: the router selects the +primary operation and the domain workflow continues to own the transaction. ## 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 `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 pending for its own confirmation, while an unknown clause becomes off-context. -The router resolves clauses from registered intent keywords and routes the -transactional operation first. The graph drains read-only pending topics before -output supervision. During an open transaction, +The router first resolves clauses from registered intent keywords, then uses the +semantic fallback only for an absent or incomplete compound plan, and routes +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 secondary request instead of causing an intent shift. diff --git a/docs/features/pt-BR/16_multi_intent_planning.md b/docs/features/pt-BR/16_multi_intent_planning.md index 92700152..35badebe 100644 --- a/docs/features/pt-BR/16_multi_intent_planning.md +++ b/docs/features/pt-BR/16_multi_intent_planning.md @@ -2,9 +2,8 @@ O `MultiIntentPlanner` reconhece solicitações independentes na mesma mensagem e 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 -invente uma sequência: o roteador escolhe a operação primária e o workflow do -domínio continua responsável pela transação. +`config/routing.yaml`. O planejador não executa operações. O roteador escolhe a +operação primária e o workflow do domínio continua responsável pela transaçã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 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 transacional: mantida pendente para confirmação própria; - 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 keywords das intents cadastradas. -2. `tool_policies.yaml` identifica a operação transacional e a torna primária. -3. A primeira operação é roteada normalmente para seu agent/workflow. -4. O `agent_graph` compõe as mensagens públicas antes do supervisor de saída. -5. Durante uma confirmação, uma frase como `sim e me manda a segunda via` +2. Se o plano estiver ausente ou contiver trecho provisoriamente fora de escopo, + o classificador LLM tenta reconhecer semanticamente as intents componentes. +3. `tool_policies.yaml` identifica a operação transacional e a torna primária. +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 troca indevida de intent. diff --git a/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc index df6d85885c4db3dc4b4db7900e4e3bef1f668a63..047d5216c38b3b02440d6582454b225c07bda2c2 100644 GIT binary patch delta 20 acmbQsJeQgKGcPX}0}zBqFW$&Ki4g!aP6Y=5 delta 20 acmbQsJeQgKGcPX}0}!ZuTC|aS5+eXMZUt%p diff --git a/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc index cb5548522a75b83c8b0af853f355fbe06649b711..fd8778da20d4c1b2889b74d19ee2f4655ef0f900 100644 GIT binary patch delta 20 acmcaBa94o)GcPX}0}zBqFW$%k^3_*FBbz4ghwyl$lc`v07k^3_*FBbz4sC-(qk-N(U087dSqW}N^ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc index e898c3f011cbde695b04dafb3a7c7e7b29e6ff32..47bd891d32f3e71be202e80b6822fc85e49ee4af 100644 GIT binary patch delta 20 acmZ3=vXq7UGcPX}0}zBqFW$&4#RLE}vjn05 delta 20 acmZ3=vXq7UGcPX}0}!ZwTC|Z{iU|NV+64vx diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-313.pyc index e712d2f94ce14c3df605ed1231b504cfb4ca64ee..d8eb7a49fdbf07ce1e4cc7ac1c72739c6dcceda7 100644 GIT binary patch delta 20 acmX>hd_tJ}GcPX}0}zBqFW$(#mlFUzP6e<4 delta 20 acmX>hd_tJ}GcPX}0}!ZwTC|aSFDC#$bp{jw diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-313.pyc index 7bbd7e2994edf0d7a70d82a1dded65f006ba3767..62703d076551e6aa9bcd9d841f2b6ff56403f236 100644 GIT binary patch delta 20 acmaFI`HqwOGcPX}0}zBqFW$)gm<0eq(FO?s delta 20 acmaFI`HqwOGcPX}0}!ZwTC|b-F$(}g_y%nN diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-313.pyc index 4babbb67ad97cb08875f16ae8a180baf39cdc8fa..eb85102bae7ac7cabeabf6102c62a92b6999a62e 100644 GIT binary patch delta 20 acmbOyKTn?fGcPX}0}zBqFW$&KnI8Z+bOlfV delta 20 acmbOyKTn?fGcPX}0}!ZwTC|aSGCu%1n+3E0 diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-313.pyc index ae1fbc0b0fd370fb6d0ce008b147ff6dc8add9c9..aab04f79119b0cce1179c6410fabdc50b6d83657 100644 GIT binary patch delta 20 acmcb_cZrYtGcPX}0}zBqFW$)Q&JF-QC)iUmFZ delta 20 acmZo+X<_01%*)Hg00gR^7H#DI$p`>5u?3<4 diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-313.pyc index 96ac00f6f13dd55bb718f8516c065ea33b6a5fc4..999cc817ce21a59a74b02854c4037b54a185487c 100644 GIT binary patch delta 20 acmbQnH;s?`GcPX}0}zBqFW$(_%?mi`M()qNyj%=G5D~q2Bezf%09Bj@l>h($ delta 22 ccmbPxg>mi`M()qNyj%=Gp!#XiMsA@j09U*Q_y7O^ diff --git a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-313.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-313.pyc index 8a9eeb090c2f945892de4fc4a5e9cde5221d82fe..3daa5593a47454deaa506ec28cf65ed8b436ecd9 100644 GIT binary patch delta 22 ccmey|%=EdLiTg7zFBbz4L_{y%$o--b09f+}jsO4v delta 22 ccmey|%=EdLiTg7zFBbz4sD4_sk^4m>09z9W@c;k- diff --git a/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-313.pyc index 30c732eca1ac3114de36c7312a8e1af2f9abec3b..1a708ad6544be1c96353294b92d464fe13e43040 100644 GIT binary patch delta 19 Zcmcb?c!QDqGcPX}0}w<+FP_MK763Oe1(W~) delta 19 Zcmcb?c!QDqGcPX}0}!ZuS~QXSEC4v?1@-^{ diff --git a/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-313.pyc index 8bb7929ced31af1ba6d1d9ce2a0b4e3b1223d309..aaa4fd7e0beb0dbf65ad70e5c82320c69202c6be 100644 GIT binary patch delta 20 acmZ2#w$zOKGcPX}0}w<+FW$&4B@F;O+XWy1 delta 20 acmZ2#w$zOKGcPX}0}!ZuTC|Z{N*Vw?^aX+d diff --git a/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-313.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-313.pyc index a3a2721b27af4685fcba81a1b81ecb425e399900..6e9cb7a3ab241dc265d300824ba1eb43b1d68af3 100644 GIT binary patch delta 20 acmcbgeLtJ~GcPX}0}w<+FW$&~#S{Qdc?Qw| delta 20 acmcbgeLtJ~GcPX}0}!ZuTC|b-iYWk3k_R*Z diff --git a/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc index 39c367612555acede75fa09b14e65901d65350fe..d7cab90e48d60d2cf1167fa929c517b7394ed3ed 100644 GIT binary patch delta 20 acmdnOw1tWLGcPX}0}w<;FW$(l$p`>8&;-l? delta 20 acmdnOw1tWLGcPX}0}!ZuTC|Z{lMw(o;sq@L diff --git a/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc index ea291b6bfe6fa10d5092a217732cb30db7e1dafa..420e8dffcc18b09f7f10230fbc4e3044fb2aabfc 100644 GIT binary patch delta 20 acmZpZYLnvr%*)Hg00fcIi#Kxr<^cdT3k7`u delta 20 acmZpZYLnvr%*)Hg00b(Z7H#DI%>w{89R=P1 diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-313.pyc index 25eb6a003bbf0ea27723bedd32dfd60d309e9c0b..d7182df26cc53db509237caabf973cc5ade34ce7 100644 GIT binary patch delta 20 acmcc5eV?2AGcPX}0}w<+FW$&~g%tol$pzv7 delta 20 acmcc5eV?2AGcPX}0}!ZwTC|b-3M&9X=>|mr diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc index fa70a44e747f1da346cf457acad71e9111980353..ed1fbf227f1268b5fc06e734538651b6c9e2ec2d 100644 GIT binary patch delta 20 acmaFJ^^lAEGcPX}0}w<+FW$%<#tHyF^#x`C delta 20 acmaFJ^^lAEGcPX}0}!ZwTC|Znj1>Su6$Qxv diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc index 436b6f35d6364e7d86f9b6eb9060b00fc882df08..61bae08bcdc9d145172cc356574977575ae73b8d 100644 GIT binary patch delta 20 acmX@*e#)KuGcPX}0}w<+FW$(#Ul{;J4+c2^ delta 20 acmX@*e#)KuGcPX}0}!ZwTC|aSzcK(vF9w_d diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc index de3f3f0c8c0b1a7f987ffe435e11f19c110edd04..062e5a9bc290087f9c7398a328ff79031686a5e5 100644 GIT binary patch delta 20 acmdm{v`vZoGcPX}0}w<+FW$(lEeHTRsRbbb delta 20 acmdm{v`vZoGcPX}0}!ZwTC|Z{TMz&}$pwS} diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-313.pyc index e250fed35e05e50c58006ba0db1c1f779b5187a3..50a34b759f32c83f700f33d451b428cf4186b9da 100644 GIT binary patch delta 22 ccmcaTlkxUUM()qNyj%=G5D~q2BliU#09We=I{*Lx delta 22 ccmcaTlkxUUM()qNyj%=Gp!#XiM(ztf09p$No&W#< diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc index 6f98d07d7d66bf24182fc5688edafda3c4145712..963724cab465862eac824275d33736305f167752 100644 GIT binary patch delta 20 acmZ3gw^Wb&GcPX}0}w<+FW$&4B@O^Ow*?FU delta 20 acmZ3gw^Wb&GcPX}0}!ZwTC|Z{N*n+@*9C6? diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc index 6dbc0149b3264e1887304f2f69be9ef032ec841f..c4b79277968c33eeb3282398d49c6bf55c3173df 100644 GIT binary patch delta 22 ccmeyem+{M9M()qNyj%=G5D~q2BlpWV0AZ{L-~a#s delta 22 ccmeyem+{M9M()qNyj%=Gp!#XiM(&q!0AtJuLjV8( diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc index 60934f023578ee4c6ef3399a8db4ded2992a7add..21dc1a6550f19bf90c1db93276fd39c0753c3f0e 100644 GIT binary patch delta 22 ccmaE{it)uNM()qNyj%=G5D~q2BX?{l09(2T4FCWD delta 22 ccmaE{it)uNM()qNyj%=Gp!#XiM()^90A1P#Z~y=R diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc index 2261f53b02f7c3b5b2a22791bd3c632bfd5116cb..bf2c81c73b1d24d1953630e37ab94f10ae7a84e7 100644 GIT binary patch delta 20 acmeAU?GEMs%*)Hg00a@yi#KvNXaN8{HU*ym delta 20 acmeAU?GEMs%*)Hg00gR^7H#Bi&;kHIRt5q9 diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-313.pyc index be67b8eca5a8dcb6b61bd33cdd1489529a85774f..9403c2c7155277dd9598b430408f8ed12f274109 100644 GIT binary patch delta 20 acmbQhI)Rn@GcPX}0}w<+FW$)A$^-y1mIUSi delta 20 acmbQhI)Rn@GcPX}0}!ZwTC|b7l?ebewgpK5 diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-313.pyc index 9c9966ad3ac704c91f6be2a78ac65db81aae0b3f..df1c3267968cbf0e89b9925c1e24a577ce900913 100644 GIT binary patch delta 20 acmX@kbDW3!GcPX}0}w<+FW$&)!v+95E(IL` delta 20 acmX@kbDW3!GcPX}0}!ZwTC|bdh7ABcP6dDf diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-313.pyc index 2445e18d91c64a982e5ab3c5bd7ab6d079a47f50..9553b2ed8209900070df9d81ee366a60cdcd6658 100644 GIT binary patch delta 20 acmaFI{*ImdGcPX}0}w<+FW$)gm>B>;j|K$* delta 20 acmaFI{*ImdGcPX}0}!ZwTC|b-F*5)|uLfuU diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-313.pyc index db39055e0c5151a8cf4e02202d50d6e9b4745174..0a6f6b0e8673c2dfe7dafc19b8b9c621a0bd6e70 100644 GIT binary patch delta 22 ccmdmYiD};@ChpI?yj%=G5D~q2Be(HN09!o=H2?qr delta 22 ccmdmYiD};@ChpI?yj%=Gp!#XiMsDMk09{=Nm;e9( diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc index 1afa0019b247272390d2a32d42a226d5774b6623..e9006a642b310682c5841d6c187ccb959a1638d5 100644 GIT binary patch delta 20 acmdlYzD1n-GcPX}0}w<+FW$(#k{bXz#|3`? delta 20 acmdlYzD1n-GcPX}0}!ZwTC|aSB{u*(=LO;b diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-313.pyc index a580e3921007d9f25d609a8dffbc4d1566b3543f..f815d3c5411d884fb976265ad37074f6efc47a1f 100644 GIT binary patch delta 20 acmeAd?ic3%%*)Hg00a@yi#Kw&Z~_1{Z3PAZ delta 20 acmeAd?ic3%%*)Hg00gR^7H#Bi;RFCSjRk1{ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-313.pyc index a101e62981864cc6f79678debc4bf381e8f63d3e..7a71e277f7d191b5dd6db1467b29ff89bf2ad4fe 100644 GIT binary patch delta 20 acmZn`Y!>AH%*)Hg00a@yi#KvtZ~y=@LAH%*)Hg00gR^7H#CN-~a$LWCcI~ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-313.pyc index 49a250a36a0c67e94703133a0c9aace9a549a344..ce1a4d85cf93d04fbf4f48712791b6a04ce9b95f 100644 GIT binary patch delta 20 acmexv`rVZKGcPX}0}w<+FW$)gMhXB)h6a-W delta 20 acmexv`rVZKGcPX}0}!ZwTC|b-jT8V&rUv!^ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-313.pyc index 82e7e46da57b9b157e78c6b74f86dd560c5a92f2..19bcadb51df53a71a00b8ab9756647532aec9878 100644 GIT binary patch delta 20 acmX>sb6AG^GcPX}0}w<+FW$&)!3O|5)&)5L delta 20 acmX>sb6AG^GcPX}0}!ZwTC|bdf)4;b_63{( diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-313.pyc index bbf2cb75c6361041fe4a06cf15d2936c56c83a3e..3da66dd7ea605944cb7a952cafbd8514a62df269 100644 GIT binary patch delta 20 acmca9dsCMCGcPX}0}w<+FW$&~jt>AqY6blO delta 20 acmca9dsCMCGcPX}0}!ZwTC|b-93KEfiUwc+ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-313.pyc index 54882cd316d3f48566cc1b3a7c222653ae0337ae..f1404d7ce10bfb990d29d9cf7a148a369d65f7e8 100644 GIT binary patch delta 20 acmZ2rwZMw|GcPX}0}w<+FW$&4DhmKRr3D)R delta 20 acmZ2rwZMw|GcPX}0}!ZwTC|Z{R2Bd|#RYx< diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc index 738d967fceea86e6ee16a2e231cda257e75efbf2..e89c2722e1e1c71f8b70936ec9d8d59e7415380a 100644 GIT binary patch delta 20 acmX@$dcc+YGcPX}0}w<+FW$(#RS5t?HU<^| delta 20 acmX@$dcc+YGcPX}0}!ZwTC|aSs}cZ3Rt9+h diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc index c9af6e39fb44117422a773e189ff237acc0f9cd7..09d07e138d3e530d4d2aa95f429b6523ce72251f 100644 GIT binary patch delta 20 acmcbSb0dfQGcPX}0}w<+FW$)QYX$&Ih6X?Y delta 20 acmcbSb0dfQGcPX}0}!ZwTC|bd*9-tnrUs(` diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-313.pyc index 367c823ff27e4bf9340dd13bd6d19c5b15ed948f..9a4db63101b5d1dcbd7c7ff1a618c0f395e9272e 100644 GIT binary patch delta 20 acmeyK^gW6DGcPX}0}w<+FW$(VV+a6F@dktd delta 20 acmeyK^gW6DGcPX}0}!ZwTC|Zn#}EKf5eDY~ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc index 0988eff547a8ac4bc8c4d99ccc8e661e66bf06c3..e086b178acfb37fd9e50f0757dc63614c658cf75 100644 GIT binary patch delta 20 acmcc3e4Cm3GcPX}0}w<+FW$&~fe`>c1qH$Y delta 20 acmcc3e4Cm3GcPX}0}!ZwTC|b-0wVxGB?ct` diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc index efbe6b8bb5e5cec23f67b8cecb46c1beee6ee78b..e6f4625510a514d925f8701beae5792589a0f48d 100644 GIT binary patch delta 20 acmeyU`%#zsGcPX}0}w<+FW$)gObh@=at3Vx delta 20 acmeyU`%#zsGcPX}0}!ZwTC|b-nHT^`k_ONK diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc index 84b19f8fc632b12e12e5880d556d473f166a327f..ce8fd813997f09f8b909a1d3f8d5d16cb7e03d2f 100644 GIT binary patch delta 20 acmZ1~Y|Lk1)O delta 20 acmZ1pF delta 22 ccmey?$@s04k^3_*FBbz4sD4_sk^8j^09+gg#{d8T diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-313.pyc index 2ce265f6ac88defd811c911787931c9719e14ac9..4521f68388b9008123b80948003997f0da261643 100644 GIT binary patch delta 20 acmca?ec77(GcPX}0}w<+FW$&~LKXl-!3H(} delta 20 acmca?ec77(GcPX}0}!ZwTC|b-ge(9?;Rcxi diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc index 31d97eeb0111ab7c00f90baa6d1167577e4033d2..752de0e610de58e787542ee9942a621568028b69 100644 GIT binary patch delta 22 ccmccK!Fauck^3_*FBbz4L_{y%$nE0-08^j_g#Z8m delta 22 ccmccK!Fauck^3_*FBbz4sD4_sk=w@w09C*S=l}o! diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc index c947a70ed1e9f72e1b02ceb2a1be01b36030aeac..db480d7dc34e2b37617432545d509b6cbdd98493 100644 GIT binary patch delta 20 acmaFm_{x#{GcPX}0}w<+FW$&~UjYC~GzN+Q delta 20 acmaFm_{x#{GcPX}0}!ZwTC|b-z5)PCR0iz; diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-313.pyc index 3ee4c5594911b4fd746b48a4ba6a07acc6ca6426..5f4023bddbb23bda1771912289089157724e7fa9 100644 GIT binary patch delta 20 acmaFF@rZ-_GcPX}0}w<+FW$%<&H?~F)CFV! delta 20 acmaFF@rZ-_GcPX}0}!ZwTC|ZnoCN?t^aaNN diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-313.pyc index c4cce796677a117e2ef6f4f137109e6581f6df73..ff9d2d5b6e9e7b97755c2b2958f26c93c0634012 100644 GIT binary patch delta 20 acmca0aY2InGcPX}0}w<+FW$)Q$^!sCOa)c| delta 20 acmca0aY2InGcPX}0}!ZwTC|bdl?MPoYz4Uh diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc index 2171e2e85e24bfb1dec83d3b49c1c6813f2e8e83..9212d475458882dafa94f6938a8856c2d3dcaa79 100644 GIT binary patch delta 20 acmZo;ZDZyB%*)Hg00a@yi#KvtGXVfG1_a0e delta 20 acmZo;ZDZyB%*)Hg00gR^7H#CNW&!{+CIu@1 diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-313.pyc index 383f5c7a82da392bc338d451d10c6c9eeb89f857..baf476b15daf624e380929a6d2b459283a4680ed 100644 GIT binary patch delta 20 acmZ3)zKEUsGcPX}0}w<+FW$&Kof!Z%uLU6h delta 20 acmZ3)zKEUsGcPX}0}!ZwTC|aSIx_$_&jo}4 diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-313.pyc index 2340921bd1cbb20c5d6294c6b63291f9475bbbed..8934ee8e94cc951a32c7d5e6d923a92106d8d0ba 100644 GIT binary patch delta 20 acmZqVZRF+t%*)Hg00a@yi#KwYu>k-vVg$_q delta 20 acmZqVZRF+t%*)Hg00gR^7H#A%V*>y)f(0-D diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-313.pyc index a6892a37332d2dfb9538660fe8e0ed57017978af..a1d01dac0342348fd4942ff27b7ab84efd50c72d 100644 GIT binary patch delta 20 acmeBF?^Ngh%*)Hg00a@yi#KxD2?GE&R|O^j delta 20 acmeBF?^Ngh%*)Hg00gR^7H#CN69xb{cLj+6 diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-313.pyc index 04fcca85114c1126c0f04e11a8114e79cd9c30c0..24be80faa104fc89d790dd4f92162e7374036eed 100644 GIT binary patch delta 20 acmdnzzR#WeGcPX}0}w<+FW$(#Ss4IBF9sC= delta 20 acmdnzzR#WeGcPX}0}!ZwTC|aSvoZihPX>4Z diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc index ef27b0365afec6e912b037368a4d5c6657630508..6924bce5681616660dd65b4045e1270baf575842 100644 GIT binary patch delta 20 acmZ1ywj_-EGcPX}0}w<+FW$&4sSN-?Lj`RB delta 20 acmZ1ywj_-EGcPX}0}!ZwTC|Z{QX2q5V+GIv diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc index 031c6db0c976270a2d1c7c0abf11700c2ffa1735..27537fb7f1b66bca142fe5d26f6d5f3ceaca9670 100644 GIT binary patch delta 20 acmca8c~O%4GcPX}0}w<+FW$&~j0XTem<8Ja delta 20 acmca8c~O%4GcPX}0}!ZwTC|b-7!LqJxCTA| diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc index 05fe8ace342a6159daf82e4e00498f71338845b3..77453b42833fcfead3fe80a475eaec80dcc3c21f 100644 GIT binary patch delta 20 acmZpbYL(*t%*)Hg00a@yi#Kxr;sF3O+y!|6 delta 20 acmZpbYL(*t%*)Hg00gR^7H#DI#RC8~`~}GcPX}0}w<+FW$%GcPX}0}!ZwTC|ZnMgagxxCUYX diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc index a280463231c8753740771be4e95e7adc4bf24d19..5f3c4ad96a6fa463cae30077e3773b621d935828 100644 GIT binary patch delta 20 acmbQvGM$C{GcPX}0}w<+FW$(_!vp{_iUfH8 delta 20 acmbQvGM$C{GcPX}0}!ZwTC|ayhY0{Qss!8s diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc index 34c982f536bf16f10cc93fa92986f26a11176134..e22e83be0c7eed7de5ff9648fcc8ed7b1f15d0d0 100644 GIT binary patch delta 20 acmcc3cbkvlaY};wGcPX}0}w<;FW$&)&jSEGV+BP3 delta 20 acmX>laY};wGcPX}0}!ZwTC|bdo(BLwd+%aGcPX}0}w<;FW$(VAOrwJK?TMD delta 20 acmaE@@>+%aGcPX}0}!ZwTC|ZnK?ndwS_UWp diff --git a/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-313.pyc index f2b28f373a5958179cc856e30211041e7b34ef9e..0e772978457e9d40957822aec5c44df2096ecaa5 100644 GIT binary patch delta 20 acmaFE@`i=`GcPX}0}w<+FW$(V$OHgC(gk<` delta 20 acmaFE@`i=`GcPX}0}!ZuTC|ZnkqH1n>jl~X diff --git a/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc index 513c1ac69fe7be88e1d2d525fd0226b5d7fc8ae1..fbf09e6b39510d00d9bbea1b0d30709baff5afab 100644 GIT binary patch delta 10688 zcmbU{3s76vmG4PU9}qvA|6gE!vH^n)_>VvMi*4-sfrE`>Sx66%5fZ*ng5Wk5NhgU@ z$1(P8V!KIWr%qDSxLtcmrs;OK6F1Y(rcD<@w~!a7&34-EHks}=>ul1d)9Idbo`itX z%+6}y=)QCBJ@?%6zxU~@w+(Mj8ItZMCdLc!Y45mpy!-R#ld{D9=gXfD%k^@6j&NLJ z>2iZ?qgIBzN=~3wW|mMa$cZ_EoOC3)-iXr$fn^ak8L%n!h6pa3aEk!9cm|h4xKzNU z&ERqgmkzj$Be_5^tdq)T5^op!PUMeq>E9EM=`hp>Q+Xi_#b^{>?h`5G^E|nYQT52tmH_Dsj6*NL*mGWkJ zCE=^&Epi>Ts=JMjCVtfL2%iY2*WCwf9yK17o)BcQ&nTN@bDObEsx!z27;J@Q#6C$j zrV2Yt1;H=2O2tB(z;7>43%7~&qQ1rGx8KlasL)Y@2h_KBi6FEYRD)e85p058=$0Io zlRFM5?!bV;?7<$z9$?;Xuiq8)`n&B+IT2FSpuLL)`s|&7kl&+tD&fi1rwj&IZ&hH> zuXyarfY+n=-AZ-XA!+G>eucS$0p|4j)gTMGgWiB&1+-4q=M1R|b4CbjCZNxTG@BX- zF}LCjD)$B55hEj}%>YvcLA?7N*jJWDMn--*9j5j2pvh$R-GYAD@w;z zh&!BFHT?ft)*-e0)&gs20>jYYuxjyM6_w-y-D#4?>kewhZUq47O)~-T_G{(=mk&%p zlYCw^sF{MHexKslY0*rC*GwLzKiH!gdzB$A&h7GhydGCj(M(-vD_T-NQ@Rw!6ps@I z0FgnLuUADL?D!cT=DVc9a53^!Hzjiq|MFW`3h)W&Kg1M(Nt zR{{KCSeUk@jMSc4Go6}#$Cf^#Jl#5FE1s|wznxh+Vw}z^y0Yu?uB+~+T1MjTq~>4p z-bkHFt(r`&y6O1l@>|QN!Yi64S2RuMmR#9*dE;bm<(p}hA6SH}vfo>Uf+bguTt4#5 z(UG{fvhpq+x+#vvO=hhaG5sPnYovZU*M4CSj4Y`9{bC_y@rO1cDeIEyIq5m&(*0A3 zRTGI-Z|4_(`phM;Mv8UuUD$=-F!5*4XJl%&K6gLtSPl7ts%DM47QfI_0ahmnqas89 zaF|&hd@+u@zM^JFx;{O%^+$|GQ{NicjTPbNH_gw5a z-*Gi{GQD&%rR=on7q*ns_0y?YUqH#hAP_)85`!=%xDEV+lC;%!@aQLmSw1Rk5Tjmz z@yiY&amJSo9g!p@2)t%EgAbR*Z;E!#p44V25js#*^oa#Yzp>329p`F{xx7JlbE(as zhlR*<$=Y@ZJir9flVNU>Aj6m>VWm_8a&BR$Ab#w8W;m1uEji%xy1hZyYhQisS|A!$ zeQWI@Tr$2X;P3LXzDTbpU=OLG*PdnGfZY!fSFxiW18eP|XjG;qbp`@HQYcBE;R2e~ z?NXJlfX@SQ*GiEZVlAu2Gz&@(f#ZQqSff6rN-zghZPzuO={yl~`Mkj)=kbuITY)E7 z7w4~nVJqQZJqch~xRbPKq~c=rrOwHuqTwAMnuUav5z9r}dE0p2%E^?vDO>%7t$sQ= z<8;!UYbG;S-0c2l->tr}z*IxaL_^DD z!~V(4{WNhpvGi)s)x+b<+s6+b8*g`w+d9XkPTeeKB0MmIDg=#-cPr*uNz4w~z&>RD zjg@h{+?~ShE%E%%$JXY>>}k$Oqim=*@*;OeWZ;^x0Te2(gJot}-6FI)$UCNac<>y+ z8)Wm^odRT2howc6{E!*R3^Xa|QhT)&@Z^5Te<)rOb|aV%Xp^1r1vN_q$JPVRA%UVv zaS(!C!5||QGgO4bsF_GdYz;iIwE$E!{25i|IK3*yj5#amYGs>X;6|J=006XUOL}Z@ zBy_3kYUgCKV=8(1^#hZ(nkieugsoxH*0FlZwt2#~dD7N2y!F$E&K@~!%fFg7VJn@o z9lV}4Ub}U|u@#y>l*acT{O6=`=^$y6|H|-S)iz*)44SqAdBPWPL0VDW0j97O(5adG zU8<^hP>B43@xiS-a7G*gj5w?r$D})*khOwdw-W{B?Ft1W>2#}Jf`H6^?xS{Q~xmdcGu7sVd_ zR8q4TCq1eFNRB6u8u4S;5L`@9hS9aeq&P%#U$=F+s- z4CFwy0stw{hwl>6LJbV8?a;#e9o4H#1YSI{RHi5N15=NuE6-{7qS}75}~9S1EC;`c{>FqBk-kSVI7eneCeivUiH^v zRIq>sslEWcYA^W9Zz0-DC#U{>p~+~&kPxv}o>H8-WF}6;On7cKXD{&P;(YO!yr(!1 zbn;Mfso079X%^UAU{LY2GB?t^i~wz|8~))_vdLl5UC82u!&-e!tRh05j2 z(0wwldPbqoz%#poAeC>ZSiS2>Y z$QQrH?^G0sACLX1qDZVE(qwt$gJhEAU_>9S*O8KR=1z>>sj!&fXI6D-?$QZwX)*OdXXNNgms*3IQb$b9fe-j2Y4T09+Pg2W^=c zM9J$JcrK|=;^CYaVat)cP@-WJ^-01c^(T-LrJGfhZ_okQbp)dbzJ_3K4$|G|A?!f# z2*0xID|!lgh+hq5^JA6!7kO<^5>hs2r*Ysxe!FsW_HJyx3}BwEy})y;D#Ix-MYTaM zI9^`KMDm((>l(d&zC}vViuHFMD-_zFVyyA)E_2bs{wBJYp^iIQt{iEiVn1{{^ z8el`{E|6qHaKEGL3!NN%J?7fq0EDVnro%c5*ZJO>aznnz2WobKSHD^_?06LhvD@>f zqWwjtM#APO_tsVzibc+AE5oHYiL{AIVLwLj27u9o1x;?AwaqgzRFszJbh>>|YPuDl z&*_9?H8Bse5;p0q{|wha0P5h4D{6uLcUBkh$5*uGdCOp&7N^HdN ze*jQ{M%1=GLL`C){^IIdU1}duEc?^yjZpinTO*4H$Ih)eBbhJbP&csM$6&c#!D5}i;aJk$cWd8`` z;1<#qbj_-)ZUJ)Pq6(MN7VX)yx0$NaXgSp~_WI@r4DD!BEtDqzhLtarlqel7WaR?d z4uT#0+SVl&awb9KZ*2XNcxtR?+jkAAnC~?k+_QCgyP@8Mdi~tkhMm<0+j;2Ft1dSm zXkH_dojXmX?SE0_y!axWn%MEu`AVy1*?97S0mj}($g@;kt7uuIk;*zKhcrR zt9Hk={sVS=8^Klt6d^K@bqv%j6IyVaMA14Qu|xuwW9P6Rd5WBdFo)>AbCiE!cdqy( ze_{9cp{(rNbI8_v5C_vi25gbEPPX(IqKQx_N{vn@P&BhZm)ECIJ+obtux`_X3`I8y zi+D}yLo5*@l4p^|qrA3#XA!Z9guzqs-bb@~{l^tIoJZ&`g?adw+6$d*1I}27pcg=- z3tC!^M+rj31cw&5-f}y;nf@9BZrM~yvW=Lq=n5uAqfwfNb`)4akM5u?e5l7 zbYc%w*daH)F$wtfiB%|6OyI1Vdk>YbdLNtQ$R9*Wu#bt(fIH~d;s*j=eE9)kQsm3DRPr^4?MF(H z6qW;8ys88v2Talj+(GpBD}E21^XV*0k)0vW6s*Vv$g?%epo{t84G}~8air>2^+o>j z;k|2%028gzQMb&FE0R{pMo6`fBTZtZ9D7l(Y$IRaQDn#yxwB)Lczx_lN0JF_?n}q~ z7BQ8_^*oxu95`z!f@c2ho+Tz$4sHH^Pi_$f9ufvdY0VUZoiIk3F%8G3^J;Ha!A@k& z+>iINLv$Gq)(G08OC`3Od%T_E`(r=w9yGwZ1wPdf4ZaustHoA6?k`z~+NV#OF#n?2 zl^_Tmrf7ewxz!YXi?dH`HTw<+!+#b0$FDMWiEIc~ zhKikH*d}PRRs5qsQ@w>;mC#y}eps5h=xs%*Q;EMHTXir?e>ubN?cWxzf-|X#din#M zOf&QFI`{O>J3CzCo!wJAdM0-C{4~GrX8SAZPxG6`{R5|4AT>@UFMTt4>Gjo9$#oOS zb#LXDUiIJXdc{4Nzhx?O%XrF`JGsSE@QNk3@_PHL13y$JbLFXY`Sf<0S^Q>l@zn;P zFp<1;I-grlBsVpQZ>7usmbv7QY6CFx`OT?YD#Y6v;+A6Rc4i^A8^kRo((P3x(Ee_& zxTQ?`Zk`3(B_hHyfc)Tz{pBbesx#nH>9f$*#N*5jd!Ab;+|S=Qu|iyPfi1I<*I|^@ zGWf{3j6~Lk62cJ5GDLoemG7)Xk{E!Q6Nj0hMC(x)92Y3SqAX))b+(I!c)ZB$s) zMb`nR#CxO1M2aJ?BP&GZC)lECghQgA*zmnV^!z627MK#ryk%ZE`0v|1qcyJ|~*KoW5FXArj=0o4*quoc1%1RK!t76a;GfxkVp$VNk`_x#w$Ln8)pn4kXKlFkQk z{EImA27<3gX#j_$cT)5)4#JVzVx_AKvZfcx4T$^rc3-7k{Z-1R@&ZB2SmOPqVm+!^ zv%n=Ry_CQM2*`toqXEqkcowdPpp$o>+9Dz2eB}NN{@ST$DrZhE(b;H{b7tc~l_5CJ z&xSWb2!11+Y!DCecOEz<-r$W77Hv%ff|1;H5MN7gV=TbHFp-odVcDe_x_VeLQpOB! zhmT&zU&gQnQJGMES_O-NbYj1UKJ+N=TbN9AG zvd(Iv&Q(56!do18XY9F8e<@7tn|hVvA*TxO|CJN$GA;^lj{ExIEj)V>m;4%n8$56> zSA3bDIaet@KlaMGAyKIYTH8krOv3(lcz`Il8KJrCRDe6%5o$FtoqCdqgt zOZP)0D)JeU9O@RX<&b|iii2o}wAUMa--YEV1=vFieGgkN^T#jb#rNPy1Q*9%x{zs1 zM5f>twE{=H#iyTGeJ>Gw6rQ)UZ^F396)Pi-h=mwO#LP=b!Km{wv*g^Uq#<<#Z;$mo zc|qKH8K2!aPl{dE>PGQx#2R(BQ5$renoI34q7nRVY{#V{aUF3+$2ejSYbYw7z*lMa zNM??&ehWt+_#b}lGTiKp{qAyycqmTaEZOHt91+_wsfUgwlr|*VtR|^0_`*cGX<37W2@LmS3R)sZ%h?gfqn<0pUdMR?La>tf;NuIP7jZ1K; zg46V+SuBs?mcgFt;7hkBQs2CONw1?UkQryEzeud5d`dBqT4aXU0si1s1!PH$PJ-Uf{={*%-covzH@SgPcAkqO* z(H&-iD{8Si$~ddWakkv)-5R%ac1N9>rDn&fC|iQR^T1lCYVc9Mro_?F+Vh>i(+Qba zn}U<`pL_1P=bn3B_vX!u=4W0pXMDb3L8^&t;0BpTI6l@)-!Ldx6RwY*kbQW?<((g%%KR6ceS^X=}Wxr-X_MD4p=-L@{sv{ z*`9HvE|2W2TePUqtzrL&s@wX9BmSsv(*hBp>ejwUWLUS4`ZY}r>hgn(quKd5sT9nz z219|UD3W()x>AaX@HzcA$rJYdsS5}Z0D1CXGMC#c`BVO&wMbgBZc<9+j;ufC=vhM5 zMk8TO_3a(=4~L@Taw30?jAged4f1E%txB!@B)dqdjHl+bE3pO=p{IW74 zL>7eR04xMxwTcMy*mTRV8m1jYMQD_@FnA%tV-t<^OLy)aQ?+O)64vehu(n?nx+4$? zN7VyS7OB~Y$&DXT#q9E>+*)Oc{NLPB)}+@%rlo;Nvw&2Q4csYK1J49#PhuUw+yr#H zP@`ia%oRZNI}#kHZ7Xu zAM?x8c>U#IsElV8{Hv0#JJo%mpc)RSB2WIh@DZh5_7!bb*2$j~4b`*|qsPKV(bEV0 znlH)Q3K4ApJ+i%c<1XDYphk6zKRiw+HA=@n_oVE6Qie_0oNURhkbqOy>;&BIJEzZx z4W$>$SW&UkC9f9iE7lSN4yp%Jx&XQX)&m%}1jeS^2n=9_w3k#E{<=}tm;7AWB|j+n zxBzF}tK0UB1qamaS1!|;ZmRbHyCQu5_rYh~8Vcw*>@#rYmqn9~5qDJz_0)SbRj z|2XBDpx7&azqs7BJ1H0z&{KT<{^8+1e_%*t%0f^5^@tTu>U<8NI}(y~OJvLlULzkA z$#GAq(kUPDl-i-ZHYER{XIcD1&+p9ZIZl&4NOsRz;-Ftqhc&NI4pj$@#2MC11iCiVV$5i3pFLLBmLy2-se$?Pn{wxKBR0yiED8_W2_F( zjD>*PJz<>1 zF`2!p*8Gu4u3WW=cM!11wb={h5a%p`ZMuIuH~ z~nw*HI@RmeA1=ebyGg=DNTbdEzNzVImTvDR5tTo0Us`nz^S{%dFt0*>zrAn~k{FkluZgCi3XykZ ziC9dp0aZt}*p6|OXzKg&|~sm$^zXE|Fc;k~EJ z#7mI#GQfWjnCp*Qy2`UMNR0ReIADi_jZb#9SHmSe=2>NGJ~MvW<^H=|D1tOOVft-m z{z>hT{ipUnI)0(R^X&B(G8?CyjWgMSlf#UoieF;gUlGtq#^Wk-#mLLu#Pc0)JzufmGE;$7*bO;Is_=Pv8WhOD)+*z8 zF4HA)>sh5YzIfZK=3G>4J&jtk{?Gu$HMP>A_%}B9o5?(2JI05uFZT3 z$WewbUnR_wxT<^$DmNHdNuXsAP$zL!ndu#yH!96#+|`IC)pnwR=Gvlpj!ixplT!(&Suu=_$Xz95l~qWiyXl8fc&Iy zV+E@T!4#A!6fU|m6yBo-s158egR4dE4wM(`j>Og6sOoEJWP14f0k?NEzL5%btJpgn z73n01IXkS7!O0*=({lpJR&)BsFM=}?$jJg?^XXt=S{B4Ww#b%M!P>lE1LcFBnr0Ul zr7!4m@GjmZuMO5#vu(ZxD;In=8fwj~oRcYk6D*0X0+CbsC}DcBe}Kx2uV2vX$Nq>I zYM>@p4Quo^pb2DE;RaW#rbZLDIW{xB8;p*s;h=E~-w2VMp`jtC8^f~^n!01ZUxY*9 z0Rgx0ICB$MIvG*7tTfXKdMbOP4`(J6EXk+EXU|7A2%)Tt6QejU(I>x9E6m@RWKsW8 z$?yq5$ob=MQ#Q+d0IHH%Y4Rd!2whOszU)xAt-kq+E$DGa1y0w7BAttvPW!&wur-Iceq2oerTEEJbm}l z2967)COx0h-N>jv5H+&j^mSLXWB*8Gf_jVHch_!2T!_B{+(1LRof@M-RZtt=2pTM9 z7_I|Y9kT>O1N5M#+xx}>Lu!;Yq8xJm?ltE36`6YYHJc-)_|N(B&BL8BUWo%0@nGb% znbgUtm4la0E>&RYU>4Hxt#tjmefs{zq5m`lu$1S3@ieAk(_f|G@pAfNWHmDL(JAV%$uPDKpTOug>H=N@Pzq26Fk_Gp@j2hdZ-ZEXblQW4rs+PDeCJqpS|w)i=urIX zv6E)|05R#MGJA4ij4B)+8ighXG5vn9BA*(q4knSp$vP%5lR5PqwZETAS%}I%W$h?s zUX3^TH+7iHJwPecx{Z(t(COPmxmvQksc|2df_P`J7Fp)d9>Dh4FYi9oi8~|u z%5m9oqGBD=pl}n1p1PBYrMg~-h#=R6DBX(ANH_NnijV1Y&Q<#>A_;)C@uyB?T4Ee+ zs5~7ujBtkFy3>zOt~LXNk$JgB@WPx9+(gxFp{P2di6Y|wIFOBg5_G`@&4!jy6=lTo zH%8A_oU}+j4Q-9LoZ6}=F?s*#JC#8EPp2>2S0y*e`A4@!$405iX(nzxMGcRQsCcRp zG5QwVn5~4yT+VKm%Gt6W)@p$`f(f>uI!f&#F3|MG8ayCYVjAmeqcY~x=iiqL#Yn{*d81&Y#tmUJ$*rWaSB3sd%V$ypiD|)@AMZQr%+|{ zx zP2V8S5ntj3RIuu->x}BG^+{qSOYyX%Cf8=N7oirwbMdZor=PAa1r$G zB<%>)#F-g?J}}CqTU3EkKMh`vmpoOW7+#nQBCD6|7%6&_Vy=naGvEdIr9AMXO%%Pa z{^(X^_Z1@0X4zZ0;hfnqpJO&=VHr{yo7Js&hBn+3>&yvbn1yeJzmfZ%9;dYb$LM%jTwb6&x()4D(pnbRg4@wJF3_t_#jwgU>;?|HG#)0>*D%D5bx?2K`J!$HluSKNV5 zzSG2kodNQ2%p6Ol_uHsTu$nF lVyAy5?N)imbDi>^pNnK1G%MSbPfh&m>LI!G$4_y2`# str: + """Recover the originating request from bounded, framework-owned evidence.""" + preferred_keys = ('operator_instructions', 'original_user_request', 'query', 'source_text') + + def walk(value: Any, depth: int = 0) -> str: + if depth > 7: + return '' + if isinstance(value, dict): + for key in preferred_keys: + candidate = value.get(key) + if isinstance(candidate, str) and candidate.strip(): + return candidate.strip() + for candidate in value.values(): + found = walk(candidate, depth + 1) + if found: + return found + elif isinstance(value, (list, tuple)): + for candidate in value: + found = walk(candidate, depth + 1) + if found: + return found + return '' + + for key in ('transaction_evidence', 'mcp_results', 'evidence', 'selected_tool_call', 'pending_tool_call'): + found = walk(context.get(key)) + if found: + return found + return '' + + +def _quality_judge_question(question: Any, context: dict[str, Any]) -> str: + current = str(question or '') + # The runtime/router owns natural-language confirmation classification. + # Judges consume that structured decision and never classify lexical tokens. + if not bool(context.get('confirmation_received')): + return current + original = _find_original_transaction_request(context) + if not original or original.strip().casefold() == current.strip().casefold(): + return current + return f"Solicitação original: {original}\nConfirmação do usuário neste turno: {current}" + + +def _is_response_quality_judge(judge: Any) -> bool: + name = str(getattr(judge, 'name', '') or '').strip().casefold() + task = str(getattr(judge, 'task', '') or '').strip().casefold() + return 'response_quality' in name or name in {'quality', 'rqlt'} or task == 'rqlt' + + class JudgeResult(BaseModel): name: str score: float @@ -508,9 +556,10 @@ class JudgePipeline: return [] async def _evaluate(judge): evaluate = judge.evaluate + judge_question = _quality_judge_question(question, ctx) if _is_response_quality_judge(judge) else question if inspect.iscoroutinefunction(evaluate): - return await evaluate(question, answer, ctx) - result = await asyncio.to_thread(evaluate, question, answer, ctx) + return await evaluate(judge_question, answer, ctx) + result = await asyncio.to_thread(evaluate, judge_question, answer, ctx) if inspect.isawaitable(result): return await result return result diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-313.pyc index c982ee8057ee2cee2c946729d85d627dbdac2263..ea7723da4cf090d742f838b873e9149363080077 100644 GIT binary patch delta 20 acmcb|e2c3H delta 20 acmZouZBym`%*)Hg00gR^7H#CN76Je_wgr0t diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-313.pyc index d05e49d44fe24bd5a3eac015527c84c4443c112c..8c65792aa79d3e3672258a44b278f9c4659b3c41 100644 GIT binary patch delta 20 acmdn4vt5V#GcPX}0}w<;FW$(lBL)CHMFl

^VGcPX}0}w<;FW$(#P6_}&-38hJ delta 20 acmdmKy3>^VGcPX}0}!ZwTC|aSofH5;_69rv diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-313.pyc index 8af63eb24dc8d3bc298366374588642cf33db458..b11c0204464a9f5ce4fe2c0fcdb5b36f73963490 100644 GIT binary patch delta 20 acmcb{dySX-GcPX}0}w<;FW$&~nhgLxu?5Wl delta 20 acmcb{dySX-GcPX}0}!ZwTC|b-G#daw$_6h0 diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-313.pyc index 43b94734c3f92bbb670a23022b4d979e860d0440..0982f8cb136c1da3bb0ee73aa08be7e3995c828f 100644 GIT binary patch delta 22 ccmZp9!r1bJk^3_*FBbz4L`E;($o;br09EG)asU7T delta 22 ccmZp9!r1bJk^3_*FBbz4sD4_sk^5&M09XJA)Bpeg diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-313.pyc index ff0d9324af503f91cee26ebf73bdb30fe37d7332..91e9e27906d42c618f4dea67c722b9afc53a6270 100644 GIT binary patch delta 20 acmZ4KxYCjPGcPX}0}w<;FW$&KPXPcw69vcs delta 20 acmZ4KxYCjPGcPX}0}!ZwTC|aSo&o?tECwn7 diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc index ad97060a12c9cab32379472a2ccff71c9ce99b04..a3fa80545835ae28a8492c112204868e5b70e5cc 100644 GIT binary patch delta 20 acmaEm_#lz{GcPX}0}w<;FW$&~)c^oYI|jV~ delta 20 acmaEm_#lz{GcPX}0}!ZwTC|b-ssR8_R0kgb diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-313.pyc index e0b5a6702fd7c368e3edc072b9ef71d32f1a0e69..e70f0ede80fef2a5c21aec8c2ce568d0419f0b6d 100644 GIT binary patch delta 20 acmdnwwaJV7GcPX}0}w<;FW$(lt_lD^#07c) delta 20 acmdnwwaJV7GcPX}0}!ZwTC|Z{T@?UA-38nL diff --git a/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-313.pyc index 4d602976b0d776fb3752603e9105799f0b92a70f..8764649831053dc5e7cc9b8b18cfc6d2b7b20082 100644 GIT binary patch delta 19 Zcmcb?c!QDqGcPX}0}w<+FP_MK763Oe1(W~) delta 19 Zcmcb?c!QDqGcPX}0}!ZuS~QXSEC4v?1@-^{ diff --git a/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-313.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-313.pyc index 470d06179324a7185399ee7f5c91dc571b9822ae..c37e1efa0d17d0a9f0977acbfb30bbfea09575e5 100644 GIT binary patch delta 20 acmeB{?w02M%*)Hg00a@yi#KvN@B#od@dXY5 delta 20 acmeB{?w02M%*)Hg00b(Z7H#Bi-~|9T3I%Wg diff --git a/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-313.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-313.pyc index b8dec2db152fdd1f734b6f60ff1ccfc2e5639536..e94ab292a1d3b40004da03ab03d080b2e86e0e21 100644 GIT binary patch delta 20 acmbOxI!%=OGcPX}0}w<+FW$)A%>@88&IKR< delta 20 acmbOxI!%=OGcPX}0}!ZuTC|b7n+pIp=LLcQ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-313.pyc index b91eb2a722715eae2cc8d2bb159574a222dc1f7f..15633666de451d129e267d28944d7755eeb94330 100644 GIT binary patch delta 20 acmeyu^@WT3GcPX}0}zBqFW$(V$qE2L<^`Sr delta 20 acmeyu^@WT3GcPX}0}!ZwTC|ZnlNA6&4F&=L diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-313.pyc index 221f212712284107c6889ea3ffe4a40eb1990f86..9b2dfe1720b8e44dfb6934f0a43112fd211d0b68 100644 GIT binary patch delta 22 ccmX@PoblvxM()qNyj%=G5FWjFBlo^w09OYGCjbBd delta 22 ccmX@PoblvxM()qNyj%=Gp!#XiM(%yV09h^vivR!s diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-313.pyc index fd75cd4d88b55b2c58059f9d314065faece7683b..94a0e2616328983078fe4802cdf0900a898d6a00 100644 GIT binary patch delta 20 acmca(dB>9bGcPX}0}zBqFW$&~Q3e1-*#=7h delta 20 acmca(dB>9bGcPX}0}!ZwTC|b-q6`2?00yrB diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-313.pyc index 2c167ff049ca630013edd052fb7101f80dfb8c6d..b9567f3c855042d1bf719c4ec91820c5f03dcb3a 100644 GIT binary patch delta 20 acmdlavq^^gGcPX}0}zBqFW$(l&IbTGCj|un delta 20 acmdlavq^^gGcPX}0}!ZwTC|Z{oeuy!P6cTI diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-313.pyc index b1947d21dea0b1b79913ae35dbc1621732ce08d5..dee1bde730eebfbcb0fbeb88d9eb0bded9c12d31 100644 GIT binary patch delta 20 acmZn>Xc6H4%*)Hg00iODi#KxrWCs8Xc6H4%*)Hg00gR^7H#DI$qoQDX9d6j diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-313.pyc index 27ca857fb71f23be39ed24ed2b36dc29f0192f03..bfb7a89904940decfeadc32fcab45a359fea8c58 100644 GIT binary patch delta 20 acmey&@|lJEGcPX}0}zBqFW$(V!2|$6;{}WW delta 20 acmey&@|lJEGcPX}0}!ZwTC|Zng9!jb3I*^0 diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-313.pyc index 840e6ba465884cd065627d27408564c8a80b80f4..74645fdf965d22f8a4393c72f70d6680a0bf822e 100644 GIT binary patch delta 20 acmZqSZsF$s%*)Hg00iODi#KvtvH}1xiUiOA delta 20 acmZqSZsF$s%*)Hg00gR^7H#CNWCZ{-u>~{$ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-313.pyc index 9c70f7a92fb45e3a475fd7d87643f8e898948f44..12a17b67d2343e9e86d57a8f3385c9f107d3e872 100644 GIT binary patch delta 20 acmaE=_Ee4gGcPX}0}zBqFW$%~VGcPX}0}zBqFW$(#LIMCjO$EFF delta 20 acmdmNxY>~VGcPX}0}!ZwTC|aSg#-XVbOs;* diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-313.pyc index 78e790327615426a5b9f20ed5309a1ec425f0942..70e9f4d302c407494ae9bebe8d50cb3812ef554b 100644 GIT binary patch delta 20 acmeyQ{z;wtGcPX}0}zBqFW$)gTo?dGxCUSV delta 20 acmeyQ{z;wtGcPX}0}!ZwTC|b-xiA1o-v-10 diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-313.pyc index 54969b6ed70478c9543f1631e8f123185ff6be51..09163f854d89ba850a345f94d6b254aa73358d99 100644 GIT binary patch delta 20 acmcaAbybS{GcPX}0}zBqFW$)Q#R~vGRt0GQ delta 20 acmcaAbybS{GcPX}0}!ZwTC|bdix&VveFe<` diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-313.pyc index 310750e687cd5bb4468f8cd3d1e0d3526dbd89e4..edcda5b278ead3a50f4055814f68676c89727d0b 100644 GIT binary patch delta 20 acmZ3(w}y}VGcPX}0}zBqFW$(l$PNHEI0VoD delta 20 acmZ3(w}y}VGcPX}0}!ZwTC|Z{ksSazUj;M( diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/telemetry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/telemetry.cpython-313.pyc index 1403568adbaa51b2d8d3dfb882f1f3932b7eba33..deb82cf10bc5817ff453fb254f9b7632e1acc8a0 100644 GIT binary patch delta 22 ccmX>*llkmSX710tyj%=G5FWjFBln>*09I57lmGw# delta 22 ccmX>*llkmSX710tyj%=Gp!#XiM(#sr09bnm_y7O^ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc index 65093788144fde6d31cecf249f51fb767bb8f999..f1008fdbc7f40762dc2576ac91850f2eff5eca20 100644 GIT binary patch delta 20 acmez3{Kc93GcPX}0}zBqFW$)gQV{@41_rDE delta 20 acmez3{Kc93GcPX}0}!ZwTC|b-r6K@LEe8+) diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-313.pyc index 0895aa48d59a818db7febed3b1f36988da16b933..93dc35b08be44fa1bc1ce15f22e5bf92cab947a5 100644 GIT binary patch delta 20 acmZpcYL?>u%*)Hg00iODi#Kxr-~j+Mg#~f| delta 20 acmZpcYL?>u%*)Hg00gR^7H#DI!2>_m1*8A~ delta 19 Zcmcc1c$bm;GcPX}0}!ZwS~QXS5&$`-1_l5C diff --git a/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-313.pyc index d82d14bf01e8838ecdff4e9032fd5f22bd593e42..0095c968fed802f360b40bc8e37a87ebbb1ab041 100644 GIT binary patch delta 22 ccmaF+jOpz&ChpI?yj%=G5E;FABX`nf0A@c2^#A|> delta 22 ccmaF+jOpz&ChpI?yj%=Gp!#XiM((7|0BBeUR{#J2 diff --git a/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-313.pyc index 6876be87f74b5c9e07472790f2ec6565f5d800fe..a0efd0680eac40171d0d61532c7825707ee0a842 100644 GIT binary patch delta 20 acmZ2ex~7!-GcPX}0}w<;FW$(#&U6 diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc index ef04e2691cce6d1a971a8715c4990b7b396fb8e9..eaaa2b5808805ad35294bf3867308d9f36f546bc 100644 GIT binary patch delta 20 acmbR1H`kB*GcPX}0}w<;FW$&4qz(W+4h2O3 delta 20 acmbR1H`kB*GcPX}0}!ZuTC|Z{NF4w`AO)rX diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc index 853b2c2e7017d7851f931ddef5a1e26fa7c3c550..142e1668b3d143ed7ce0d92068b1ea1e5c29320b 100644 GIT binary patch delta 20 acmbOnIysd4GcPX}0}w<;FW$)Ap#=aweFeAx delta 20 acmbOnIysd4GcPX}0}!ZwTC|b7Lkj>vmIfLC diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-313.pyc index bcb6f09dca2d29042e2d7222885ff80544fa68d3..2f1ba423077a0e286417e001e9aefa0fda05f589 100644 GIT binary patch delta 22 ccmaDjk@4X~M()qNyj%=G5D~q2Blk5A09UaGIRF3v delta 22 ccmaDjk@4X~M()qNyj%=Gpz>+aM(%4K09nchn*aa+ diff --git a/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-313.pyc index f8fa52ddc84229b509cc290c330ecc4fb25ae2e2..472278b0c9c59c93a6f9f5e4491ee47cf3e5caf6 100644 GIT binary patch delta 19 Zcmcb|c#o0$GcPX}0}zBqFP_MK82~s41*HH0 delta 19 Zcmcb|c#o0$GcPX}0}!ZuS~QXSG5|Tn1_%HE diff --git a/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-313.pyc index 216844ec58538a062db86eb9034df51d58ee06e7..312153faf5d7d72bbe3eaf2af7afb5bf1c253731 100644 GIT binary patch delta 20 acmeBo?sw+?%*)Hg00iODi#Kw&C;|XGJ_UUM delta 20 acmeBo?sw+?%*)Hg00b(Z7H#BiQ3L=zUIpL) diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc index 3c58cd4cabfeacb44e72166f029d5b85541b326f..333011b8cf0c2e357e64aa053f5b31d5a6efcef6 100644 GIT binary patch delta 20 acmeBV?PTTt%*)Hg00fcIi#KxDF#!NEg#^+7 delta 20 acmeBV?PTTt%*)Hg00gR^7H#CNV*&s(o&_`j diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-313.pyc index 7c458e2d2717b3411ac9de68b4fcbaf50c5e842d..a75ba967d3e748b148bea45f46549272a0ff5095 100644 GIT binary patch delta 20 acmZn`Z5HMJ%*)Hg00fcIi#KvtZ~*`^-2~_W delta 20 acmZn`Z5HMJ%*)Hg00gR^7H#CN-~s?N_614+ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-313.pyc index f8213f79eac0519d4f4ea7e024f1f05c175d4bf4..44f00e267d917a8c37fa8bf5420723edd845e741 100644 GIT binary patch delta 20 acmdmAv%iM>GcPX}0}w<;FW$&)Vg~?8?FJqI delta 20 acmdmAv%iM>GcPX}0}!ZwTC|bd#0~&V1_pot diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc index 1c415ff5a6f59e8391dda3168f1e2aaf4cc06448..572ecf90fb9dd82ba04b0268a7cacfc6d3648a6b 100644 GIT binary patch delta 8766 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 diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc index 3829534f76ef217219a80694f091d7cc2a1d2595..d8b32772eeea01f48b11db6db99ec8c969241585 100644 GIT binary patch delta 20 acmbOrJVBWIGcPX}0}w<;FW$)A$_W58oCOL1 delta 20 acmbOrJVBWIGcPX}0}!ZwTC|b7l@kCqwFPVd diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/multi_intent.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/multi_intent.cpython-313.pyc index f701a67c4b43b45c850b640d3611aa74e51c6e19..2419ff365063943222b55a78c14b9d950644a937 100644 GIT binary patch delta 9638 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 VB|*cafhOCMIb;w1#aptK=wBHqPu2hc delta 1508 zcmZ`(&rc(D6o20t+L`H0JN-#1&|g5I6&DKY2DFQt-GmetVS#ZH4cQRVmZfePa0(jM zY&Pg&)e9!y5cl9=qnAB+(5!mdlX@d@ZG*9d?14X_Su~nxjPE<8qz9d3KHvBA^S<-m z%Y1j?he6k=)9CtLFOJH9^Qr^ffXn2&V0pn3CuoS)zZC9P!d6?$eMDL+`_h zqJA)QS(;o`@=G&|#9KLG$R!GSR#i`YiM}5>!{S2Kod4VQW9LwYS6t z8#a0(NOnx?Xs9HFwL6)CGz{`N_y6eUoGk=h*-ou1O|)WVn+M@x@| zy=g$X&%y-rVnc;tU~em9M$iN;uJsRzlf-aFK$m+!cQ(Ig8spb^fOp6~KW9_GaJ4km zMSm6t$UsX|c~w{G%TjOaRI}V{3MU}aIL;8gj^6m$Y}0t9W}z6a$n5I?GVTG!-gV5x z-MZ+5scBprWKEupGS30bD#)iU2I=>5C*|cqkE**fxJ8z49DQz9D{;OkxLGr2%zX2N`j4v=D3!O&;^wj4v`!N{1Sv0lR}GUv zy07-rs@j=}q48K)TQTybf@uyg&6Zm$mhzZp5t=Hq*|&}2+uMa>sa(iy82J@*r|hL^ zcc95)!3n&skCLD z4@3J4e?C(?PJxpGM@pckbXVz9zvtdOUi1Cy-UXf<1myV`cMv1 RouteDecision: allowed = [i for i in self.intents if i.enabled] allowed_payload = [ diff --git a/libs/agent_framework/src/agent_framework/routing/multi_intent.py b/libs/agent_framework/src/agent_framework/routing/multi_intent.py index 27354e17..b135326d 100644 --- a/libs/agent_framework/src/agent_framework/routing/multi_intent.py +++ b/libs/agent_framework/src/agent_framework/routing/multi_intent.py @@ -30,11 +30,12 @@ class MultiIntentPlan(BaseModel): class MultiIntentPlanner: - """Deterministic planner constrained by routing.yaml. + """Multi-intent planner constrained by routing.yaml. - The planner never invents agents or tools. It recognizes independently - configured intents in conjunction-separated clauses. Execution remains - owned by the agent/workflow runtime. + Deterministic recognition is attempted first. Structured semantic output + can then be validated by :meth:`plan_from_semantic`; the LLM never owns + agents, domains or tools, which are always hydrated from configured intents. + Execution remains owned by the agent/workflow runtime. """ _SPLIT = re.compile(r"\s*(?:,|;|\be\b|\bmas\b|\btamb[eé]m\b)\s*", re.I) @@ -56,6 +57,9 @@ class MultiIntentPlanner: # técnicos/overrides; sua ausência nunca desabilita a detecção. self.enabled = bool(self.config.get("enabled", True)) self.max_operations = max(2, int(self.config.get("max_operations", 4))) + self.llm_confidence_threshold = float( + self.config.get("llm_confidence_threshold", 0.65) + ) self.transactional_tools = set(transactional_tools or set()) @staticmethod @@ -88,6 +92,31 @@ class MultiIntentPlanner: def _is_transactional(self, operation: PlannedIntent) -> bool: return any(tool in self.transactional_tools for tool in operation.tools) + def looks_compound(self, text: str) -> bool: + """Return whether a turn is worth sending to the semantic fallback.""" + clauses = [ + part.strip(" .") + for part in self._SPLIT.split(str(text or "")) + if part.strip(" .") + ] + if len(clauses) < 2: + return False + return any( + self._looks_like_request(clause) or self._intent_for_clause(clause) + for clause in clauses + ) + + @classmethod + def confirmation_remainder(cls, text: str) -> str | None: + match = cls._CONFIRM_WITH_REMAINDER.match(str(text or "")) + return match.group(1).strip() if match is not None else None + + @staticmethod + def needs_semantic_fallback(plan: MultiIntentPlan | None) -> bool: + return plan is None or any( + operation.disposition == "unsupported" for operation in plan.operations + ) + @classmethod def _looks_like_request(cls, clause: str) -> bool: normalized = cls._normalize(clause) @@ -111,6 +140,103 @@ class MultiIntentPlanner: status="pending", ) + def _finalize_operations( + self, operations: list[PlannedIntent] + ) -> MultiIntentPlan | None: + if len(operations) < 2: + return None + transactional = [item for item in operations if self._is_transactional(item)] + if len(transactional) == 1: + primary_operation = transactional[0] + operations.sort(key=lambda item: item is not primary_operation) + for operation in operations[1:]: + if self._is_transactional(operation) and operation.disposition == "execute": + operation.disposition = "defer" + return MultiIntentPlan( + plan_id=f"mip-{uuid.uuid4().hex}", + operations=operations[: self.max_operations], + execution_mode="primary_with_secondary", + ) + + def _semantic_operations( + self, payload: dict[str, Any], *, allow_single: bool = False + ) -> list[PlannedIntent] | None: + try: + confidence = float(payload.get("confidence", 0.0)) + except (TypeError, ValueError): + return None + if confidence < self.llm_confidence_threshold: + return None + raw_operations = payload.get("operations") + if not isinstance(raw_operations, list): + return None + catalog = {intent.name: intent for intent in self.intents} + operations: list[PlannedIntent] = [] + seen: set[str] = set() + for raw in raw_operations[: self.max_operations]: + if not isinstance(raw, dict): + return None + source_text = str(raw.get("source_text") or "").strip() + intent_name = str(raw.get("intent") or "").strip() + if not source_text: + return None + if bool(raw.get("unsupported")): + operations.append( + self._off_context(source_text, f"op-{len(operations) + 1}") + ) + continue + intent = catalog.get(intent_name) + # Fail closed: an invented/disabled intent invalidates the semantic + # plan instead of trusting agent/tool fields supplied by the model. + if intent is None: + return None + if intent.name in seen: + continue + seen.add(intent.name) + operations.append(PlannedIntent( + operation_id=f"op-{len(operations) + 1}", + intent=intent.name, + agent=intent.agent, + domain=intent.domain, + tools=list(intent.mcp_tools), + source_text=source_text, + )) + minimum = 1 if allow_single else 2 + if len(operations) < minimum or not any(op.intent in catalog for op in operations): + return None + return operations + + def plan_from_semantic(self, payload: dict[str, Any]) -> MultiIntentPlan | None: + """Validate structured LLM output against the configured intent catalog.""" + if not self.enabled: + return None + operations = self._semantic_operations(payload) + return self._finalize_operations(operations) if operations else None + + def plan_confirmation_from_semantic( + self, + payload: dict[str, Any], + *, + primary_intent: str, + primary_agent: str, + ) -> MultiIntentPlan | None: + """Validate one semantic secondary while preserving an open transaction.""" + if not self.enabled: + return None + secondary = self._semantic_operations(payload, allow_single=True) + if not secondary or len(secondary) != 1 or secondary[0].intent == primary_intent: + return None + primary = next((item for item in self.intents if item.name == primary_intent), None) + operations = [PlannedIntent( + operation_id="op-1", + intent=primary_intent, + agent=primary_agent, + domain=primary.domain if primary else None, + tools=list(primary.mcp_tools) if primary else [], + source_text="confirmation", + ), secondary[0].model_copy(update={"operation_id": "op-2"})] + return self._finalize_operations(operations) + def plan(self, text: str) -> MultiIntentPlan | None: if not self.enabled: return None @@ -134,21 +260,9 @@ class MultiIntentPlanner: )) if not operations or len(operations) + len(unknown_clauses) < 2: return None - # Regra técnica geral: uma mutação que exige o contrato transacional é a - # operação primária. Não é necessário cadastrar cada par de intents. - transactional = [item for item in operations if self._is_transactional(item)] - if len(transactional) == 1: - primary_operation = transactional[0] - operations.sort(key=lambda item: item is not primary_operation) - for operation in operations[1:]: - if self._is_transactional(operation) and operation.disposition == "execute": - operation.disposition = "defer" for clause in unknown_clauses[: max(0, self.max_operations - len(operations))]: operations.append(self._off_context(clause, f"op-{len(operations) + 1}")) - return MultiIntentPlan( - plan_id=f"mip-{uuid.uuid4().hex}", operations=operations, - execution_mode="primary_with_secondary", - ) + return self._finalize_operations(operations) def plan_confirmation_secondary( self, text: str, *, primary_intent: str, primary_agent: str @@ -161,10 +275,9 @@ class MultiIntentPlanner: """ if not self.enabled: return None - match = self._CONFIRM_WITH_REMAINDER.match(str(text or "")) - if match is None: + clause = self.confirmation_remainder(text) + if clause is None: return None - clause = match.group(1).strip() secondary = self._intent_for_clause(clause) primary = next((item for item in self.intents if item.name == primary_intent), None) if secondary is not None and secondary.name == primary_intent: diff --git a/libs/agent_framework/src/agent_framework/routing/pending_topics.py b/libs/agent_framework/src/agent_framework/routing/pending_topics.py index 5de65c78..4a77f9ba 100644 --- a/libs/agent_framework/src/agent_framework/routing/pending_topics.py +++ b/libs/agent_framework/src/agent_framework/routing/pending_topics.py @@ -13,6 +13,7 @@ class PendingTopicDrain: answer: str pending_topics: list[dict[str, Any]] handled_topics: list[dict[str, Any]] + mcp_results: list[dict[str, Any]] async def drain_pending_topics( @@ -28,6 +29,7 @@ async def drain_pending_topics( )) remaining: list[dict[str, Any]] = [] handled = list(state.get("handled_topics") or []) + combined_mcp_results = list(state.get("mcp_results") or []) secondary_answers: list[str] = [] for topic in topics: disposition = topic.get("disposition") @@ -83,6 +85,9 @@ async def drain_pending_topics( if not answer: remaining.append(topic) continue + for evidence in (result or {}).get("mcp_results") or []: + if isinstance(evidence, dict) and evidence not in combined_mcp_results: + combined_mcp_results.append(evidence) secondary_answers.append(answer) handled.append({**topic, "status": "completed"}) @@ -93,9 +98,5 @@ async def drain_pending_topics( unique.append(answer) if unique: secondary = "\n\n".join(unique) - candidate = ( - f"{secondary}\n\n{candidate.lstrip()}".strip() - if state.get("confirmation_required") - else f"{candidate.rstrip()}\n\n{secondary}".strip() - ) - return PendingTopicDrain(candidate, remaining, handled) + candidate = f"{candidate.rstrip()}\n\n{secondary}".strip() + return PendingTopicDrain(candidate, remaining, handled, combined_mcp_results) diff --git a/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-313.pyc index a0fbec33b36e42d8ff815f6d7679383ec17f8df4..9bcad7f7a7fc1887edb917089ccab1a7f434ce37 100644 GIT binary patch delta 20 acmcb|bdQPqGcPX}0}w<;FW$%<%m@HIU diff --git a/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_parameters.cpython-313.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_parameters.cpython-313.pyc index 417545db0b84c24d873f3f288d759ddf30814fc3..d95c6edeffce77597b2f592f3c8d128fa8b11da2 100644 GIT binary patch delta 22 ccmZpi$=EoPk^3_*FBbz4L`E;($X(_G07%pZE&u=k delta 22 ccmZpi$=EoPk^3_*FBbz4sC-(qk-N+X07~Wtj{pDw diff --git a/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc index cd1f4cc42226925bc65a8022cf8c4b1761ab0ee0..2c4f45ab413903df9ba1493c1748594759ea3e5f 100644 GIT binary patch delta 19 Zcmcc0c$Ja+GcPX}0}w<;FP_MK3II081&jay delta 19 Zcmcc0c$Ja+GcPX}0}!ZwS~QXS6aYAW1?~U< diff --git a/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc index 31ae89064a8eea11932850fc8748f976ff0eb178..5288597038c377bbb184dc39e0e272071cc10219 100644 GIT binary patch delta 20 acmezB_0@~}GcPX}0}w<;FW$(Vr3wH`JO)Dm delta 20 acmezB_0@~}GcPX}0}!ZwTC|ZnOBDc3RR*O1 diff --git a/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-313.pyc index 65b6f01aaa43fc0ea3a54204f1d1bdd163b00477..094a11010ae3f40486b0c76924b7a60b408f6721 100644 GIT binary patch delta 19 Zcmcb^c!!buGcPX}0}w<;FP_MK5db&J1)%@{ delta 19 Zcmcb^c!!buGcPX}0}!ZwS~QXSA^TdIfy| delta 20 acmcbpc2SM{GcPX}0}!ZwTC|bdO&9<|lLg-Z diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-313.pyc index ccefd30a992bb7c59c1d4f4b88acc5a87d8e86d1..b3df8ea06c03594926705a695cee2c5ad05f4240 100644 GIT binary patch delta 20 acmeys_JNK2GcPX}0}w<;FW$(V$_xNN!Uc)| delta 20 acmeys_JNK2GcPX}0}!ZuTC|Znl^Fm+)CKDR diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-313.pyc index fb1dfac9faea41ede3d9c1f7ac32378d19ec1f79..1b0a21b68cb477c1a4a8af588a13d93ab16ba29e 100644 GIT binary patch delta 20 acmeC=?&RkF%*)Hg00fcIi#KxDu>t@xUIrDGcPX}0}w<;FW$)Qs{{Z=*#+GI delta 20 acmccNa>IrDGcPX}0}!ZuTC|bdR|x<|>jpjm diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-313.pyc index a01d23feb1687573528b1afbffc8acf832445bb2..c08980d58d6a30a25353e03b41b1427f44aef047 100644 GIT binary patch delta 20 acmexv{oR`TGcPX}0}w<;FW$)gMiu}{Xa=JI delta 20 acmexv{oR`TGcPX}0}!ZuTC|b-jVu66dItmm diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-313.pyc index 950bd311334a7709d8a5ca850ebd7bc1d83bf371..3ad59d88fbba000cb39141b7f9f6057832fbf6c6 100644 GIT binary patch delta 20 acmdljv|EV#GcPX}0}w<;FW$&)zzG04Fa-$! delta 20 acmdljv|EV#GcPX}0}!ZuTC|bdfD-^bLIr97 diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-313.pyc index f5f2a86af3e7c7e26b0ded66a2222c64e54cde34..b4b0d9913c4d3bc64fead43a0f8a03b608026096 100644 GIT binary patch delta 20 acmbOuI!BcIGcPX}0}w<;FW$&KkqZDe#RW3} delta 20 acmbOuI!BcIGcPX}0}!ZuTC|aSA{PKS*9DXS diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-313.pyc index 5589ff2448bd23688cf537880e86ccd91702606d..7b4574f80b2412b6a55fc4327d4768958cd120cf 100644 GIT binary patch delta 22 ccmdlri)q&^ChpI?yj%=G5E;FABe#Ap08#V?o&W#< delta 22 ccmdlri)q&^ChpI?yj%=Gpz>+aMsEFH08|DB{{R30 diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc index c99df20e8eaeabc70c1572c97f238d87a4e45070..69526bfe15ce7877c64080a11c31cd48d14b7560 100644 GIT binary patch delta 20 acmdnMzk#3oGcPX}0}w<;FW$(#lpO#$3I$*Q delta 20 acmdnMzk#3oGcPX}0}!ZuTC|aSDLVi=90kDu diff --git a/scripts/sync_pending_topics_to_tuning.py b/scripts/sync_pending_topics_to_tuning.py index 9e6c49ae..c91eaf21 100644 --- a/scripts/sync_pending_topics_to_tuning.py +++ b/scripts/sync_pending_topics_to_tuning.py @@ -94,6 +94,33 @@ def update_graph(path: Path) -> None: path.write_text(before + marker + output, encoding="utf-8") +def update_evidence_propagation(path: Path) -> None: + text = path.read_text(encoding="utf-8") + marker = ' "handled_topics": drained.handled_topics,\n' + replacement = marker + ' "mcp_results": drained.mcp_results,\n' + if replacement in text: + return + if marker not in text: + raise RuntimeError(f"Marcador de evidências não encontrado em {path}") + path.write_text(text.replace(marker, replacement), encoding="utf-8") + + +def update_guardrail_evidence_context(path: Path) -> None: + text = path.read_text(encoding="utf-8") + marker = " context = {\n **(state.get(\"context\") or {}),\n" + addition = ( + marker + + ' "evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),\n' + + ' "tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),\n' + + ' "tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),\n' + + ' "mcp_results": drained.mcp_results,\n' + ) + if addition in text: + return + text = replace_once(text, marker, addition, path) + path.write_text(text, encoding="utf-8") + + def main() -> None: tuning = ROOT / "Tuning-Performance" states = sorted(tuning.glob("**/app/state.py")) @@ -102,6 +129,8 @@ def main() -> None: update_state(path) for path in graphs: update_graph(path) + update_evidence_propagation(path) + update_guardrail_evidence_context(path) print(f"pending_topics sincronizado: {len(states)} states, {len(graphs)} graphs") diff --git a/templates/agent_template_backend/app/workflows/agent_graph.py b/templates/agent_template_backend/app/workflows/agent_graph.py index 7101db41..d1455b4c 100644 --- a/templates/agent_template_backend/app/workflows/agent_graph.py +++ b/templates/agent_template_backend/app/workflows/agent_graph.py @@ -569,6 +569,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -576,6 +577,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -644,6 +649,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py b/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py index 3df0833f..76d16dfb 100644 --- a/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py +++ b/templates/agent_template_backend_day_zero/app/workflows/agent_graph.py @@ -567,6 +567,7 @@ class AgentWorkflow: "final_answer": candidate, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "output_guardrails_already_applied": False, "supervisor_action": "disabled", "supervisor_attempt": int(state.get("supervisor_attempt", 0)), @@ -574,6 +575,10 @@ class AgentWorkflow: context = { **(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"), "agent_id": state.get("agent_id"), "session_id": state.get("conversation_key") or state.get("session_id"), @@ -642,6 +647,7 @@ class AgentWorkflow: "output_guardrails_already_applied": True, "pending_topics": drained.pending_topics, "handled_topics": drained.handled_topics, + "mcp_results": drained.mcp_results, "guardrail_decisions": state.get("guardrail_decisions", []) + [item for r in decision.results for item in (r.metadata or {}).get("legacy_decisions", [])], } diff --git a/tests/unit/test_multi_intent_planner.py b/tests/unit/test_multi_intent_planner.py index 0c720620..2f47ab81 100644 --- a/tests/unit/test_multi_intent_planner.py +++ b/tests/unit/test_multi_intent_planner.py @@ -1,3 +1,9 @@ +import json +from types import SimpleNamespace + +import pytest + +from agent_framework.routing.enterprise_router import EnterpriseRouter from agent_framework.routing.models import IntentDefinition from agent_framework.routing.multi_intent import MultiIntentPlanner @@ -64,3 +70,114 @@ def test_single_word_keyword_does_not_match_a_longer_word_prefix(): assert plan is not None assert all(item.intent != "cancel" for item in plan.operations) assert [item.intent for item in plan.operations] == ["invoice", "off_context"] + + +def test_semantic_fallback_hydrates_ownership_from_configured_intents(): + plan = _planner().plan_from_semantic({ + "confidence": 0.92, + "operations": [ + {"intent": "invoice", "source_text": "me encaminhe o boleto"}, + {"intent": "cancel", "source_text": "não quero mais o pedido"}, + ], + }) + assert plan is not None + assert [item.intent for item in plan.operations] == ["cancel", "invoice"] + assert plan.operations[0].agent == "orders" + assert plan.operations[0].tools == ["cancelar_pedido"] + + +def test_semantic_fallback_rejects_invented_intent_and_low_confidence(): + assert _planner().plan_from_semantic({ + "confidence": 0.99, + "operations": [ + {"intent": "cancel", "source_text": "não quero mais o pedido"}, + {"intent": "invented", "source_text": "faça outra coisa"}, + ], + }) is None + assert _planner().plan_from_semantic({ + "confidence": 0.2, + "operations": [ + {"intent": "cancel", "source_text": "não quero mais o pedido"}, + {"intent": "invoice", "source_text": "me encaminhe o boleto"}, + ], + }) is None + + +def test_semantic_confirmation_preserves_primary_transaction(): + plan = _planner().plan_confirmation_from_semantic( + { + "confidence": 0.9, + "operations": [ + {"intent": "invoice", "source_text": "também gostaria do boleto"}, + ], + }, + primary_intent="cancel", + primary_agent="orders", + ) + assert plan is not None + assert [item.intent for item in plan.operations] == ["cancel", "invoice"] + + +@pytest.mark.asyncio +async def test_router_uses_semantic_multi_intent_only_after_deterministic_miss(tmp_path): + routing = tmp_path / "routing.yaml" + routing.write_text(""" +router: + fallback_agent: billing +intents: + - name: cancel + agent: orders + description: Encerrar uma encomenda existente + keywords: [cancelar pedido] + mcp_tools: [cancelar_pedido] + - name: invoice + agent: billing + description: Obter documento de cobrança ou boleto + keywords: [segunda via] + mcp_tools: [consultar_fatura] +""", encoding="utf-8") + policies = tmp_path / "tool_policies.yaml" + policies.write_text(""" +defaults: + operation_type: read_only +tool_policies: + cancelar_pedido: + operation_type: transactional + require_confirmation: true +""", encoding="utf-8") + + class SemanticMultiIntentLLM: + calls = 0 + + async def ainvoke(self, messages, **kwargs): + self.calls += 1 + assert kwargs["generation_name"] == "llm.router.multi_intent" + return json.dumps({ + "confidence": 0.94, + "operations": [ + {"intent": "cancel", "source_text": "encerrar minha encomenda"}, + {"intent": "invoice", "source_text": "encaminhe o boleto"}, + ], + }) + + llm = SemanticMultiIntentLLM() + router = EnterpriseRouter(SimpleNamespace( + ROUTING_CONFIG_PATH=str(routing), + TOOL_POLICIES_PATH=str(policies), + ENABLE_LLM_ROUTER=True, + ENABLE_ROUTE_STICKINESS=False, + ), llm=llm) + decision = await router.route({ + "user_text": "quero encerrar minha encomenda e encaminhe o boleto", + "context": {}, + }) + + assert llm.calls == 1 + assert decision.method == "llm" + assert decision.intent == "cancel" + assert decision.agent == "orders" + assert decision.metadata["multi_intent_classifier"] == "llm" + assert [ + item["intent"] + for item in decision.metadata["multi_intent_plan"]["operations"] + ] == ["cancel", "invoice"] diff --git a/tests/unit/test_pending_topics_isolation.py b/tests/unit/test_pending_topics_isolation.py index e614cd7a..d5c1b69b 100644 --- a/tests/unit/test_pending_topics_isolation.py +++ b/tests/unit/test_pending_topics_isolation.py @@ -9,7 +9,10 @@ async def test_secondary_topic_does_not_inherit_primary_transaction_state(): async def billing_agent(state): captured.update(state) - return {"answer": "Aqui está a sua segunda via."} + return { + "answer": "Aqui está a sua segunda via.", + "mcp_results": [{"tool_name": "consultar_faturas", "ok": True}], + } state = { "answer": "Você confirma o cancelamento do Tamboro?", @@ -49,5 +52,10 @@ async def test_secondary_topic_does_not_inherit_primary_transaction_state(): assert captured["mcp_tools"] == ["consultar_faturas"] assert captured["available_mcp_tools"] == ["consultar_faturas"] assert captured["domain"] == "telecom_contas" - assert result.answer.startswith("Aqui está a sua segunda via.") + assert result.answer.startswith("Você confirma o cancelamento") + assert result.answer.endswith("Aqui está a sua segunda via.") assert result.pending_topics == [] + assert result.mcp_results == [ + {"tool_name": "consultar_vas"}, + {"tool_name": "consultar_faturas", "ok": True}, + ] diff --git a/tests/unit/test_tuning_pending_topics_sync.py b/tests/unit/test_tuning_pending_topics_sync.py index 23e29d46..f5f77d60 100644 --- a/tests/unit/test_tuning_pending_topics_sync.py +++ b/tests/unit/test_tuning_pending_topics_sync.py @@ -12,6 +12,8 @@ def test_all_tuning_backend_graphs_support_pending_topics(): assert "from agent_framework.routing.pending_topics import drain_pending_topics" in source, path assert '"pending_topics": drained.pending_topics' in source, path assert '"handled_topics": drained.handled_topics' in source, path + assert '"mcp_results": drained.mcp_results' in source, path + assert '"evidence": drained.mcp_results' in source, path def test_all_tuning_backend_states_expose_pending_topics(): @@ -33,6 +35,8 @@ def test_canonical_templates_delegate_drain_to_framework_helper(): assert "drained = await drain_pending_topics(" in graph_source assert '"pending_topics": drained.pending_topics' in graph_source assert '"handled_topics": drained.handled_topics' in graph_source + assert '"mcp_results": drained.mcp_results' in graph_source + assert '"evidence": drained.mcp_results' in graph_source assert "MultiIntentPlanner.public_messages" not in graph_source assert "pending_topics: list[dict[str, Any]]" in state_source assert "handled_topics: list[dict[str, Any]]" in state_source