From 3ebdaacabcb014a86c14f59e1d97b3bfb737993b Mon Sep 17 00:00:00 2001 From: "cristiano.hoshikawa" Date: Fri, 18 Sep 2026 23:12:01 -0300 Subject: [PATCH] bugfix: Multi-item --- .../Documentacao/README_MCP.md | 9 + .../IMPLEMENTACAO_MULTI_ITEM_MCP.md | 236 ++++++++++++ .../Multi_Item_MCP/README.md | 229 +++++++++++ .../Multi_Item_MCP/README_en.md | 69 ++++ .../Tuning-Performance/README.md | 1 + .../docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md | 363 ++++++++++++++++++ .../docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md | 252 ++++++++++++ .../04_mcp_integration_tools_and_policies.md | 25 ++ .../developer/en/INDEX_DEVELOPER_GUIDE.md | 5 +- .../04_mcp_integration_tools_and_policies.md | 25 ++ .../developer/pt/INDEX_DEVELOPER_GUIDE.md | 5 +- .../agent_framework/runtime/agent_runtime.py | 111 ++++++ .../__pycache__/__init__.cpython-313.pyc | Bin 413 -> 389 bytes .../__pycache__/extensions.cpython-313.pyc | Bin 2141 -> 2141 bytes .../__pycache__/idempotency.cpython-313.pyc | Bin 8914 -> 8890 bytes .../__pycache__/observer.cpython-313.pyc | Bin 17557 -> 17542 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 549 -> 534 bytes .../composite_publisher.cpython-313.pyc | Bin 2504 -> 2489 bytes .../__pycache__/event_builder.cpython-313.pyc | Bin 1262 -> 1247 bytes .../__pycache__/factory.cpython-313.pyc | Bin 3998 -> 3983 bytes .../__pycache__/publisher.cpython-313.pyc | Bin 1874 -> 1859 bytes .../tim_payload_mapper.cpython-313.pyc | Bin 9547 -> 9532 bytes .../__pycache__/tim_sequence.cpython-313.pyc | Bin 17563 -> 17548 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 516 -> 501 bytes .../__pycache__/kafka.cpython-313.pyc | Bin 1814 -> 1799 bytes .../__pycache__/langfuse.cpython-313.pyc | Bin 23174 -> 23159 bytes .../__pycache__/oci_streaming.cpython-313.pyc | Bin 1823 -> 1808 bytes .../__pycache__/pubsub.cpython-313.pyc | Bin 7442 -> 7427 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 405 -> 390 bytes .../usage_repository.cpython-313.pyc | Bin 15688 -> 15673 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 215 -> 191 bytes .../cache/__pycache__/cache.cpython-313.pyc | Bin 16525 -> 16501 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 218 -> 203 bytes .../__pycache__/adapters.cpython-313.pyc | Bin 4174 -> 4159 bytes .../channels/__pycache__/base.cpython-313.pyc | Bin 1798 -> 1783 bytes .../__pycache__/gateway.cpython-313.pyc | Bin 5773 -> 5758 bytes .../__pycache__/interruption.cpython-313.pyc | Bin 6458 -> 6443 bytes .../__pycache__/transcription.cpython-313.pyc | Bin 1431 -> 1416 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 925 -> 910 bytes .../checkpoint_repository.cpython-313.pyc | Bin 27165 -> 27150 bytes .../langgraph_saver.cpython-313.pyc | Bin 33267 -> 33252 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 216 -> 192 bytes .../agent_registry.cpython-313.pyc | Bin 6949 -> 6934 bytes .../__pycache__/settings.cpython-313.pyc | Bin 13950 -> 13926 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 308 -> 293 bytes .../mcp_gateway_client.cpython-313.pyc | Bin 3334 -> 3319 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1503 -> 1488 bytes .../__pycache__/base.cpython-313.pyc | Bin 1377 -> 1362 bytes .../__pycache__/config_loader.cpython-313.pyc | Bin 9162 -> 9147 bytes .../__pycache__/custom_rails.cpython-313.pyc | Bin 4406 -> 4391 bytes .../dlex_sanitizer.cpython-313.pyc | Bin 8489 -> 8474 bytes .../framework_llm_client.cpython-313.pyc | Bin 19675 -> 19660 bytes .../__pycache__/llm_rails.cpython-313.pyc | Bin 5925 -> 5910 bytes .../output_supervisor.cpython-313.pyc | Bin 24308 -> 24293 bytes .../parallel_executor.cpython-313.pyc | Bin 21864 -> 21849 bytes .../__pycache__/pipeline.cpython-313.pyc | Bin 10891 -> 10876 bytes .../__pycache__/rail_action.cpython-313.pyc | Bin 656 -> 641 bytes .../__pycache__/rail_decision.cpython-313.pyc | Bin 1607 -> 1592 bytes .../__pycache__/rail_result.cpython-313.pyc | Bin 1006 -> 991 bytes .../__pycache__/rails.cpython-313.pyc | Bin 45179 -> 45164 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 2996 -> 2981 bytes .../__pycache__/_compat.cpython-313.pyc | Bin 2447 -> 2432 bytes .../contestation_validation.cpython-313.pyc | Bin 2179 -> 2164 bytes .../__pycache__/contracts.cpython-313.pyc | Bin 6903 -> 6888 bytes .../__pycache__/input_size.cpython-313.pyc | Bin 3651 -> 3636 bytes .../__pycache__/llm_adapter.cpython-313.pyc | Bin 3801 -> 3786 bytes .../__pycache__/llm_client.cpython-313.pyc | Bin 7456 -> 7441 bytes .../__pycache__/llm_rails.cpython-313.pyc | Bin 8896 -> 8881 bytes .../output_sanitization.cpython-313.pyc | Bin 13912 -> 13897 bytes .../__pycache__/pipeline.cpython-313.pyc | Bin 12663 -> 12648 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 475 -> 460 bytes .../__pycache__/_context.cpython-313.pyc | Bin 5873 -> 5858 bytes .../ausencia_oferta_proativa.cpython-313.pyc | Bin 12207 -> 12192 bytes .../__pycache__/coerencia.cpython-313.pyc | Bin 4159 -> 4144 bytes .../__pycache__/dlex_in.cpython-313.pyc | Bin 1306 -> 1291 bytes .../__pycache__/dlex_out.cpython-313.pyc | Bin 1817 -> 1802 bytes .../__pycache__/fallback.cpython-313.pyc | Bin 17654 -> 17639 bytes .../__pycache__/fraseologia.cpython-313.pyc | Bin 7635 -> 7620 bytes .../__pycache__/out_of_scope.cpython-313.pyc | Bin 17495 -> 17480 bytes .../prompts/__pycache__/pinj.cpython-313.pyc | Bin 8426 -> 8411 bytes .../__pycache__/ragsec.cpython-313.pyc | Bin 1122 -> 1107 bytes .../__pycache__/revprec.cpython-313.pyc | Bin 3152 -> 3137 bytes .../prompts/__pycache__/tox.cpython-313.pyc | Bin 646 -> 631 bytes .../toxicidade_output.cpython-313.pyc | Bin 930 -> 915 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1665 -> 1650 bytes .../rails/__pycache__/alcada.cpython-313.pyc | Bin 5001 -> 4986 bytes .../rails/__pycache__/anatel.cpython-313.pyc | Bin 9150 -> 9135 bytes .../__pycache__/confirmation.cpython-313.pyc | Bin 11044 -> 11029 bytes .../rails/__pycache__/dlex_in.cpython-313.pyc | Bin 3281 -> 3266 bytes .../__pycache__/dlex_out.cpython-313.pyc | Bin 3333 -> 3318 bytes .../rails/__pycache__/ragsec.cpython-313.pyc | Bin 5464 -> 5449 bytes .../rails/__pycache__/revprec.cpython-313.pyc | Bin 5472 -> 5457 bytes .../rails/__pycache__/tox.cpython-313.pyc | Bin 8295 -> 8280 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 535 -> 520 bytes .../rules/__pycache__/alcada.cpython-313.pyc | Bin 1883 -> 1868 bytes .../__pycache__/pinj_patterns.cpython-313.pyc | Bin 3732 -> 3717 bytes .../__pycache__/tox_blocklist.cpython-313.pyc | Bin 1508 -> 1493 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 410 -> 395 bytes .../__pycache__/mcp_mapper.cpython-313.pyc | Bin 4694 -> 4679 bytes .../__pycache__/models.cpython-313.pyc | Bin 3146 -> 3131 bytes .../__pycache__/resolver.cpython-313.pyc | Bin 4715 -> 4700 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 620 -> 605 bytes .../judges/__pycache__/judge.cpython-313.pyc | Bin 43986 -> 43971 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 227 -> 212 bytes .../__pycache__/llm_client.cpython-313.pyc | Bin 5406 -> 5391 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 235 -> 220 bytes .../prompts/__pycache__/aluc.cpython-313.pyc | Bin 6531 -> 6516 bytes .../prompts/__pycache__/csi.cpython-313.pyc | Bin 1334 -> 1319 bytes .../__pycache__/fallback.cpython-313.pyc | Bin 8037 -> 8022 bytes .../prompts/__pycache__/rqlt.cpython-313.pyc | Bin 1167 -> 1152 bytes .../prompts/__pycache__/vctn.cpython-313.pyc | Bin 628 -> 613 bytes .../llm/__pycache__/__init__.cpython-313.pyc | Bin 478 -> 454 bytes .../llm/__pycache__/base.cpython-313.pyc | Bin 1625 -> 1601 bytes .../profile_resolver.cpython-313.pyc | Bin 9324 -> 9309 bytes .../llm/__pycache__/providers.cpython-313.pyc | Bin 46980 -> 46965 bytes .../structured_output.cpython-313.pyc | Bin 7461 -> 7437 bytes .../llm/__pycache__/types.cpython-313.pyc | Bin 1276 -> 1252 bytes .../mcp/__pycache__/__init__.cpython-313.pyc | Bin 475 -> 460 bytes .../mcp/__pycache__/client.cpython-313.pyc | Bin 18428 -> 18413 bytes .../mcp/__pycache__/models.cpython-313.pyc | Bin 2138 -> 2123 bytes .../mcp/__pycache__/registry.cpython-313.pyc | Bin 4742 -> 4727 bytes .../__pycache__/tool_policy.cpython-313.pyc | Bin 5687 -> 5672 bytes .../__pycache__/tool_router.cpython-313.pyc | Bin 14191 -> 14176 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1137 -> 1113 bytes .../long_term_extractor.cpython-313.pyc | Bin 2515 -> 2500 bytes .../long_term_memory.cpython-313.pyc | Bin 6841 -> 6826 bytes .../long_term_models.cpython-313.pyc | Bin 1750 -> 1735 bytes .../long_term_store.cpython-313.pyc | Bin 29188 -> 29173 bytes .../message_history.cpython-313.pyc | Bin 8361 -> 8337 bytes .../summary_memory.cpython-313.pyc | Bin 12512 -> 12488 bytes .../__pycache__/summary_store.cpython-313.pyc | Bin 9522 -> 9498 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 216 -> 192 bytes .../__pycache__/identity.cpython-313.pyc | Bin 3467 -> 3452 bytes .../__pycache__/session.cpython-313.pyc | Bin 2710 -> 2686 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1396 -> 1381 bytes .../__pycache__/code_mapper.cpython-313.pyc | Bin 21449 -> 21434 bytes .../__pycache__/context.cpython-313.pyc | Bin 7388 -> 7373 bytes .../__pycache__/event_bus.cpython-313.pyc | Bin 3634 -> 3619 bytes .../guardrail_events.cpython-313.pyc | Bin 2052 -> 2037 bytes .../__pycache__/ic_events.cpython-313.pyc | Bin 627 -> 612 bytes .../__pycache__/judge_events.cpython-313.pyc | Bin 1412 -> 1397 bytes .../langgraph_telemetry.cpython-313.pyc | Bin 4965 -> 4950 bytes .../__pycache__/llm_advisors.cpython-313.pyc | Bin 2939 -> 2924 bytes .../__pycache__/noc_contract.cpython-313.pyc | Bin 5076 -> 5061 bytes .../__pycache__/noc_otel.cpython-313.pyc | Bin 6323 -> 6308 bytes .../__pycache__/observer.cpython-313.pyc | Bin 5106 -> 5091 bytes .../__pycache__/otel.cpython-313.pyc | Bin 3413 -> 3398 bytes .../streaming_events.cpython-313.pyc | Bin 1836 -> 1821 bytes .../__pycache__/telemetry.cpython-313.pyc | Bin 52429 -> 52414 bytes .../__pycache__/token_cost.cpython-313.pyc | Bin 8692 -> 8677 bytes .../workflow_events.cpython-313.pyc | Bin 3331 -> 3316 bytes .../oci/__pycache__/__init__.cpython-313.pyc | Bin 213 -> 198 bytes .../oci/__pycache__/auth.cpython-313.pyc | Bin 3245 -> 3230 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 221 -> 197 bytes .../__pycache__/oracle_store.cpython-313.pyc | Bin 45933 -> 45918 bytes .../__pycache__/sqlite_store.cpython-313.pyc | Bin 15020 -> 14996 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 456 -> 432 bytes .../__pycache__/renderers.cpython-313.pyc | Bin 4319 -> 4295 bytes .../rag/__pycache__/__init__.cpython-313.pyc | Bin 711 -> 696 bytes .../embedding_provider.cpython-313.pyc | Bin 6518 -> 6503 bytes .../__pycache__/graph_store.cpython-313.pyc | Bin 5529 -> 5514 bytes .../rag/__pycache__/ingest.cpython-313.pyc | Bin 12582 -> 12567 bytes .../__pycache__/kbdb_service.cpython-313.pyc | Bin 15501 -> 15486 bytes .../__pycache__/rag_service.cpython-313.pyc | Bin 10899 -> 10884 bytes .../__pycache__/vector_store.cpython-313.pyc | Bin 18657 -> 18642 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 222 -> 207 bytes .../session_repository.cpython-313.pyc | Bin 8591 -> 8576 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 649 -> 634 bytes .../__pycache__/config_loader.cpython-313.pyc | Bin 2691 -> 2676 bytes .../__pycache__/continuity.cpython-313.pyc | Bin 15935 -> 15920 bytes .../enterprise_router.cpython-313.pyc | Bin 82180 -> 82165 bytes .../__pycache__/models.cpython-313.pyc | Bin 2448 -> 2433 bytes .../__pycache__/multi_intent.cpython-313.pyc | Bin 20268 -> 20253 bytes .../pending_topics.cpython-313.pyc | Bin 16134 -> 16119 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 350 -> 326 bytes .../__pycache__/agent_runtime.cpython-313.pyc | Bin 206215 -> 211750 bytes .../transaction_parameters.cpython-313.pyc | Bin 19585 -> 19561 bytes .../agent_framework/runtime/agent_runtime.py | 111 ++++++ .../sse/__pycache__/__init__.cpython-313.pyc | Bin 213 -> 198 bytes .../sse/__pycache__/events.cpython-313.pyc | Bin 9589 -> 9574 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 220 -> 196 bytes .../__pycache__/supervisor.cpython-313.pyc | Bin 5405 -> 5381 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 880 -> 856 bytes .../__pycache__/graph.cpython-313.pyc | Bin 1417 -> 1393 bytes .../input_contract.cpython-313.pyc | Bin 8792 -> 8768 bytes .../__pycache__/models.cpython-313.pyc | Bin 7671 -> 7647 bytes .../__pycache__/registry.cpython-313.pyc | Bin 2363 -> 2339 bytes .../__pycache__/repository.cpython-313.pyc | Bin 2716 -> 2692 bytes .../__pycache__/runtime.cpython-313.pyc | Bin 36154 -> 36130 bytes .../__pycache__/tool_executor.cpython-313.pyc | Bin 1968 -> 1944 bytes .../specs/SPEC-010-Agent-Development.md | 18 + .../templates/agent_template_backend/.env | 250 ++++++++++++ .../agent_template_backend/README.md | 9 + .../app/__pycache__/__init__.cpython-313.pyc | Bin 145 -> 181 bytes .../app/__pycache__/main.cpython-313.pyc | Bin 36677 -> 36999 bytes .../app/__pycache__/state.cpython-313.pyc | Bin 2973 -> 3311 bytes .../__pycache__/billing_agent.cpython-313.pyc | Bin 5216 -> 5677 bytes .../__pycache__/orders_agent.cpython-313.pyc | Bin 5124 -> 5585 bytes .../__pycache__/product_agent.cpython-313.pyc | Bin 5240 -> 6425 bytes .../__pycache__/prompting.cpython-313.pyc | Bin 1142 -> 1178 bytes .../__pycache__/runtime.cpython-313.pyc | Bin 344 -> 465 bytes .../__pycache__/support_agent.cpython-313.pyc | Bin 5136 -> 5597 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 159 -> 204 bytes .../telemetry_observer.cpython-313.pyc | Bin 4770 -> 4815 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 290 -> 287 bytes .../tool_renderers.cpython-313.pyc | Bin 4366 -> 4334 bytes .../__pycache__/agent_graph.cpython-313.pyc | Bin 56786 -> 61763 bytes .../data/agent_framework.db | Bin 0 -> 20480 bytes .../docs/MCP_MULTI_ITEM.md | 363 ++++++++++++++++++ .../README_DAY_ZERO.md | 5 + .../docs/MCP_MULTI_ITEM.md | 363 ++++++++++++++++++ .../conftest.cpython-313-pytest-9.0.2.pyc | Bin 801 -> 785 bytes ...documentation.cpython-313-pytest-9.0.2.pyc | Bin 0 -> 26081 bytes ...documentation.cpython-313-pytest-9.0.2.pyc | Bin 0 -> 8387 bytes ...agent_example.cpython-313-pytest-9.0.2.pyc | Bin 0 -> 20483 bytes .../tests/test_multi_item_documentation.py | 51 +++ .../test_multi_item_result_normalization.py | 87 +++++ 217 files changed, 2583 insertions(+), 4 deletions(-) create mode 100644 agent_framework_oci/Tuning-Performance/Multi_Item_MCP/IMPLEMENTACAO_MULTI_ITEM_MCP.md create mode 100644 agent_framework_oci/Tuning-Performance/Multi_Item_MCP/README.md create mode 100644 agent_framework_oci/Tuning-Performance/Multi_Item_MCP/README_en.md create mode 100644 agent_framework_oci/docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md create mode 100644 agent_framework_oci/docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md create mode 100644 agent_framework_oci/templates/agent_template_backend/.env create mode 100644 agent_framework_oci/templates/agent_template_backend/data/agent_framework.db create mode 100644 agent_framework_oci/templates/agent_template_backend/docs/MCP_MULTI_ITEM.md create mode 100644 agent_framework_oci/templates/agent_template_backend_day_zero/docs/MCP_MULTI_ITEM.md create mode 100644 agent_framework_oci/tests/__pycache__/test_advanced_developer_documentation.cpython-313-pytest-9.0.2.pyc create mode 100644 agent_framework_oci/tests/__pycache__/test_multi_item_documentation.cpython-313-pytest-9.0.2.pyc create mode 100644 agent_framework_oci/tests/__pycache__/test_readme_financeiro_agent_example.cpython-313-pytest-9.0.2.pyc create mode 100644 agent_framework_oci/tests/test_multi_item_documentation.py create mode 100644 agent_framework_oci/tests/test_multi_item_result_normalization.py diff --git a/agent_framework_oci/Documentacao/README_MCP.md b/agent_framework_oci/Documentacao/README_MCP.md index 5397002f..247fe2e8 100644 --- a/agent_framework_oci/Documentacao/README_MCP.md +++ b/agent_framework_oci/Documentacao/README_MCP.md @@ -77,3 +77,12 @@ No compose, o backend usa `config/mcp_servers.docker.yaml` para apontar para `te ## Operações read-only e transacionais Use `config/tool_policies.yaml` no backend para classificar somente as operações que precisam de tratamento adicional. A validação é aplicada no roteador central antes do MCP Gateway/Server. O arquivo é opcional e templates antigos continuam usando as políticas já presentes em `tools.yaml`. A configuração completa e o roteiro de migração estão em [README_TOOL_POLICIES.md](README_TOOL_POLICIES.md). + + +## Chamadas MCP multi-item + +Para operações com listas de produtos, pedidos, ativos ou outros recursos, **não implemente loops de chamadas MCP dentro do agente**. O framework possui contrato genérico para parâmetros `array/list`, pre-validation, confirmação e resultado por item (`SUCCESS`, `PARTIAL_SUCCESS`, `FAILED`). + +Guia completo: [MCP Multi-item — Guia do Desenvolvedor](../docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md). + +A tool primária deve retornar `results[]` com `success` ou `ok` booleano por item. Em workflows, use preferencialmente `output[tool_name].results`. diff --git a/agent_framework_oci/Tuning-Performance/Multi_Item_MCP/IMPLEMENTACAO_MULTI_ITEM_MCP.md b/agent_framework_oci/Tuning-Performance/Multi_Item_MCP/IMPLEMENTACAO_MULTI_ITEM_MCP.md new file mode 100644 index 00000000..8c0662cc --- /dev/null +++ b/agent_framework_oci/Tuning-Performance/Multi_Item_MCP/IMPLEMENTACAO_MULTI_ITEM_MCP.md @@ -0,0 +1,236 @@ +# Implementação prática — MCP Multi-Item + +Este documento mostra o caminho mínimo para adicionar uma operação multi-item a um agente sem criar lógica paralela no código do agente. + +## 1. Modele uma única operação lógica + +Exemplo de requisito: + +```text +quero cancelar Produto A, Produto B e Produto C +``` + +A operação lógica deve continuar sendo uma só: + +```text +cancelar_produtos +``` + +Não crie `cancelar_produto_1`, `cancelar_produto_2`, loops no agent ou intents artificiais por item. + +## 2. Declare a coleção em `tools.yaml` + +```yaml +tools: + cancelar_produtos: + description: Cancela um ou mais produtos do cliente. + mcp_server: contas + enabled: true + tool_type: action + confirmation_required: true + requires: [items] + args_schema: + items: + type: array + label: os produtos + description: Lista de produtos a cancelar. + user_prompt: Quais produtos deseja cancelar? +``` + +Também é aceito `type: list` quando o projeto já usa essa forma. + +## 3. Use a policy transacional existente + +```yaml +tool_policies: + cancelar_produtos: + operation_type: transactional + require_confirmation: true + requires: [items] + pre_validation: + enabled: true + tool: validar_produtos_cancelamento + fail_open: false +``` + +Nenhuma chave específica de multi-item é necessária. + +## 4. Canonicalize os itens no MCP validator + +Entrada possível: + +```json +{ + "items": ["produto a", "produto b", "produto c"] +} +``` + +Saída recomendada: + +```json +{ + "eligible": true, + "status": "ELIGIBLE", + "transaction_decision": { + "resolved_arguments": { + "items": [ + {"name": "Produto A", "id": "1001"}, + {"name": "Produto B", "id": "1002"}, + {"name": "Produto C", "id": "1003"} + ] + }, + "target_tool": "cancelar_produtos", + "confirmation_message": "Você confirma o cancelamento de Produto A, Produto B e Produto C?" + } +} +``` + +O validator deve ser side-effect-free. + +## 5. Não transforme uma falha individual em rejeição global + +Caso: + +```text +A = válido +B = inválido +C = válido +``` + +Se A e C ainda podem ser executados, não use simplesmente: + +```json +{ + "eligible": false, + "reason": "B inválido" +} +``` + +Isso encerraria a transação inteira. + +Prefira manter a transação elegível quando houver item acionável e preservar informação suficiente para a tool primária produzir o resultado final por item. + +## 6. Execute a coleção no MCP Server ou workflow + +### Backend com API batch + +```python +async def cancelar_produtos(items): + response = await backend.cancel_batch(items) + return normalize_results(response) +``` + +### Backend com API apenas unitária + +```python +async def cancelar_produtos(items): + results = [] + for item in items: + try: + response = await backend.cancel_one(item) + results.append({ + "name": item["name"], + "success": True, + "response": response, + }) + except Exception as exc: + results.append({ + "name": item["name"], + "success": False, + "error": str(exc), + }) + return {"results": results} +``` + +O loop acima pertence ao MCP/workflow, **não ao Agent**. + +## 7. Retorne `results[]` por item + +Contrato mínimo: + +```json +{ + "results": [ + {"name": "Produto A", "success": true}, + {"name": "Produto B", "success": false, "error": "not_found"}, + {"name": "Produto C", "success": true} + ] +} +``` + +O framework aceita `success` ou `ok` booleano por item. + +## 8. Resultado interpretado pelo framework + +No exemplo anterior: + +```text +items_count = 3 +items_succeeded_count = 2 +items_failed_count = 1 +multi_item_status = PARTIAL_SUCCESS +``` + +O framework preserva os resultados terminais e fornece esse contexto para composição/presentation. + +## 9. Workflow com etapa auxiliar + +Estrutura recomendada: + +```json +{ + "status": "COMPLETED", + "output": { + "cancelar_produtos": { + "results": [ + {"name": "A", "success": true}, + {"name": "B", "success": true} + ] + }, + "registrar_analitica": { + "success": false, + "error": "analytics unavailable" + } + } +} +``` + +O resultado autoritativo da operação principal deve estar em: + +```text +workflow.output[cancelar_produtos].results +``` + +Assim uma falha auxiliar não converte A e B em falha operacional. + +## 10. Checklist do desenvolvedor + +Antes de criar código adicional, verifique: + +- [ ] existe uma única tool lógica para a operação; +- [ ] a coleção está declarada como `array` ou `list` em `tools.yaml`; +- [ ] confirmação/pre-validation usam `tool_policies.yaml` existente; +- [ ] canonicalização pertence ao MCP validator; +- [ ] fan-out, se necessário, pertence ao MCP Server/workflow; +- [ ] a tool primária devolve `results[]`; +- [ ] cada item contém `success` ou `ok` booleano; +- [ ] sucessos parciais não são apagados por uma falha global posterior; +- [ ] a apresentação comunica sucesso/falha por item; +- [ ] não foi criado um segundo motor multi-item no Agent. + +## 11. Testes mínimos recomendados + +Cubra ao menos: + +```text +1 item / sucesso +N itens / todos sucesso +N itens / sucesso parcial +N itens / todos falha +item não canonicalizado +confirmação única para N itens +falha auxiliar após sucesso primário +replay/idempotência da mesma operação +``` + +Para detalhes do contrato interno do runtime, consulte `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md`. diff --git a/agent_framework_oci/Tuning-Performance/Multi_Item_MCP/README.md b/agent_framework_oci/Tuning-Performance/Multi_Item_MCP/README.md new file mode 100644 index 00000000..629eb417 --- /dev/null +++ b/agent_framework_oci/Tuning-Performance/Multi_Item_MCP/README.md @@ -0,0 +1,229 @@ +# Multi-Item MCP + +Capability de referência para operações MCP que precisam processar **mais de um item do mesmo tipo** em uma única intenção: produtos, pedidos, VAS, ativos, faturas, linhas, contratos ou recursos. + +> Esta capability é **framework-native**. Ela não exige um motor multi-item dentro do agente e não adiciona novos atributos obrigatórios a `tools.yaml` ou `tool_policies.yaml`. + +## Quando usar + +Use quando o usuário puder solicitar, por exemplo: + +```text +cancele Produto A, Produto B e Produto C +``` + +ou: + +```text +consulte os pedidos 1001, 1002 e 1003 +``` + +O desenvolvedor deve modelar **uma operação lógica** que receba a coleção. O framework cuida de estado, confirmação e interpretação de resultados; o MCP Server ou workflow de domínio cuida da execução dos itens. + +## Divisão de responsabilidades + +```text +Agent + seleciona a operação + NÃO cria motor multi-item + + ↓ + +tools.yaml + declara array/list + NÃO exige chave multi_item + + ↓ + +tool_policies.yaml + confirmação + pre-validation + usa o mesmo contrato transacional existente + + ↓ + +MCP validator + resolve/canonicaliza os itens + pode preencher transaction_decision.resolved_arguments + + ↓ + +MCP tool / workflow + executa os itens + devolve results[] com success/ok por item + + ↓ + +Agent Framework + mantém estado + controla confirmação + interpreta results[] + preserva evidência por item + calcula SUCCESS / PARTIAL_SUCCESS / FAILED + + ↓ + +LLM / Presentation + apresenta cada sucesso/falha +``` + +## Configuração mínima + +### `tools.yaml` + +O modo de configuração continua o mesmo. Declare o parâmetro como `array` ou `list`: + +```yaml +tools: + cancelar_produtos: + description: Cancela um ou mais produtos. + mcp_server: contas + enabled: true + tool_type: action + confirmation_required: true + requires: [items] + args_schema: + items: + type: array + label: os produtos + description: Produtos solicitados pelo cliente. + user_prompt: Informe quais produtos deseja cancelar. +``` + +Não é necessário criar configuração como: + +```yaml +# NÃO EXISTE / NÃO É NECESSÁRIO +multi_item: true +multi_item_strategy: partial +fan_out: framework +``` + +### `tool_policies.yaml` + +O contrato também continua o mesmo: + +```yaml +tool_policies: + cancelar_produtos: + operation_type: transactional + require_confirmation: true + requires: [items] + pre_validation: + enabled: true + tool: validar_produtos_cancelamento + fail_open: false +``` + +## Pre-validation e lista canônica + +O validator pode transformar nomes informais em uma coleção canônica antes da confirmação: + +```json +{ + "eligible": true, + "transaction_decision": { + "resolved_arguments": { + "items": [ + {"name": "Produto A", "id": "1001"}, + {"name": "Produto B", "id": "1002"}, + {"name": "Produto C", "id": "1003"} + ] + }, + "target_tool": "cancelar_produtos", + "confirmation_message": "Você confirma o cancelamento de Produto A, Produto B e Produto C?" + } +} +``` + +### Validação parcial + +`eligible` é global para a transação. Portanto, se pelo menos um item puder ser processado, o validator **não deve reprovar o lote inteiro apenas porque outro item falhou**. + +Padrão recomendado: + +1. `eligible: true` quando existe pelo menos um item acionável; +2. preservar/canonicalizar todos os itens necessários em `resolved_arguments`; +3. executar a operação primária; +4. retornar o resultado terminal individual em `results[]`. + +Se nenhum item puder ser processado, `eligible: false` é apropriado. + +## Resultado MCP esperado + +A tool primária deve retornar `results[]` com `success` ou `ok` booleano por item: + +```json +{ + "results": [ + {"name": "Produto A", "success": true}, + {"name": "Produto B", "success": false, "error": "not_found"}, + {"name": "Produto C", "success": true} + ] +} +``` + +O framework deriva automaticamente: + +```text +PARTIAL_SUCCESS +2 succeeded +1 failed +``` + +Estados possíveis: + +| Resultado dos itens | Status do framework | +|---|---| +| todos concluídos | `SUCCESS` | +| alguns concluídos e alguns falharam | `PARTIAL_SUCCESS` | +| todos falharam | `FAILED` | + +## Uma chamada lógica, não N chamadas no agente + +Se o backend suporta batch, prefira: + +```text +Agent -> cancelar_produtos(items=[A,B,C]) -> MCP +``` + +Se o backend possui apenas API unitária, o fan-out deve ficar encapsulado no MCP Server ou no workflow de domínio: + +```text +Agent -> cancelar_produtos(items=[A,B,C]) + | + v + MCP/workflow + / | \ + A B C + \ | / + results[] +``` + +Evite: + +```python +# NÃO: lógica multi-item dentro do agente +for item in items: + await tool_router.call("cancelar_produto", {"item": item}) +``` + +## Workflow-backed tools + +Quando a operação é implementada por workflow, o caminho preferencial do resultado primário é: + +```text +workflow.output[tool_name].results +``` + +Isso permite distinguir a operação primária de etapas auxiliares. Uma falha posterior não deve apagar o sucesso terminal de itens já executados. + +## Documentação completa + +Consulte também: + +- `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md` — guia canônico em português; +- `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md` — guia canônico em inglês; +- `templates/agent_template_backend/docs/MCP_MULTI_ITEM.md` — referência junto ao template; +- `specs/SPEC-010-Agent-Development.md` — regra arquitetural de desenvolvimento. + +Para um passo a passo prático, leia `IMPLEMENTACAO_MULTI_ITEM_MCP.md` nesta pasta. diff --git a/agent_framework_oci/Tuning-Performance/Multi_Item_MCP/README_en.md b/agent_framework_oci/Tuning-Performance/Multi_Item_MCP/README_en.md new file mode 100644 index 00000000..afe5a5e7 --- /dev/null +++ b/agent_framework_oci/Tuning-Performance/Multi_Item_MCP/README_en.md @@ -0,0 +1,69 @@ +# Multi-Item MCP + +Reference capability for MCP operations that process **multiple items of the same kind** in one user intent: products, orders, services, assets, invoices, lines, contracts, or resources. + +This capability is **framework-native**. It does not require a multi-item engine in the agent and does not introduce new mandatory keys in `tools.yaml` or `tool_policies.yaml`. + +```text +Agent selects the operation; no fan-out engine + -> tools.yaml declares array/list + -> tool_policies.yaml confirmation + pre-validation + -> MCP validator resolves/canonicalizes items + -> MCP tool/workflow executes items and returns results[] + -> Agent Framework preserves per-item evidence and derives + SUCCESS / PARTIAL_SUCCESS / FAILED + -> Presentation reports each success/failure +``` + +## Minimal configuration + +`tools.yaml` keeps the existing list contract: + +```yaml +tools: + cancel_products: + requires: [items] + args_schema: + items: + type: array +``` + +`tool_policies.yaml` also keeps the current transaction contract: + +```yaml +tool_policies: + cancel_products: + operation_type: transactional + require_confirmation: true + requires: [items] + pre_validation: + enabled: true + tool: validate_products_for_cancellation + fail_open: false +``` + +No `multi_item: true`, framework fan-out flag, or extra agent code is required. + +## MCP result contract + +The primary tool should return `results[]` with boolean `success` or `ok` per item: + +```json +{ + "results": [ + {"name": "A", "success": true}, + {"name": "B", "success": false, "error": "not_found"}, + {"name": "C", "success": true} + ] +} +``` + +The framework derives `PARTIAL_SUCCESS` for the example above and preserves the successful items. + +If the downstream system only supports single-item APIs, put the fan-out inside the MCP Server or domain workflow, not inside the agent. + +For the complete contract see: + +- `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md` +- `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md` +- `IMPLEMENTACAO_MULTI_ITEM_MCP.md` diff --git a/agent_framework_oci/Tuning-Performance/README.md b/agent_framework_oci/Tuning-Performance/README.md index 4f527547..d03dc6cf 100644 --- a/agent_framework_oci/Tuning-Performance/README.md +++ b/agent_framework_oci/Tuning-Performance/README.md @@ -8,3 +8,4 @@ Variantes e documentos de referência para comparar funcionalidades e impacto de - `Deterministic_Transactional_Workflow`: transações multi-etapas executadas por workflow LangGraph determinístico após clarification e confirmação. - `Transaction_Evidence`: persistência e correlação de resultados transacionais como evidência operacional para turnos posteriores e groundedness. - `Transaction_Pre_Validation`: pré-validação MCP side-effect-free antes da confirmação transacional; regras de elegibilidade permanecem no domínio. +- `Multi_Item_MCP`: operações MCP sobre listas de produtos/pedidos/serviços/ativos com confirmação única, canonicalização e resultado por item (`SUCCESS` / `PARTIAL_SUCCESS` / `FAILED`), sem criar motor multi-item no agente. diff --git a/agent_framework_oci/docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md b/agent_framework_oci/docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md new file mode 100644 index 00000000..6d5244f3 --- /dev/null +++ b/agent_framework_oci/docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md @@ -0,0 +1,363 @@ +# MCP Multi-item — Guia do Desenvolvedor + +## Objetivo + +Use este guia quando uma única intenção do usuário precisa operar sobre **mais de um item do mesmo tipo** em uma chamada MCP, por exemplo: + +- cancelar vários VAS/produtos; +- devolver ou consultar vários pedidos; +- alterar vários ativos; +- processar uma lista de faturas, linhas, contratos ou recursos. + +O framework já possui contratos genéricos para **coleta de listas**, **pré-validação/canonicalização**, **confirmação transacional**, **execução MCP** e **normalização do resultado por item**. O desenvolvedor não deve criar um segundo motor de multi-item dentro do agente. + +## Regra principal + +**Não faça loop de negócio no agente.** O agente declara a tool e seus parâmetros; o runtime mantém estado, confirmação e evidência. A operação em lote deve ser exposta como uma tool MCP que aceite uma coleção, ou como uma tool transacional apoiada por um workflow/MCP que processe a coleção. + +Fluxo recomendado: + +```text +Usuário cita N itens + -> Router/Agent seleciona a tool + -> Runtime coleta/reconcilia parâmetro array/list + -> (opcional) pre-validation canonicaliza itens + -> Runtime pede UMA confirmação coerente para o conjunto + -> MCP recebe a coleção + -> MCP/workflow processa item a item + -> MCP devolve results[] com success/ok por item + -> Framework normaliza SUCCESS / PARTIAL_SUCCESS / FAILED + -> Composição final relata sucessos e falhas individualmente +``` + +## 1. Declarar um parâmetro de lista em `tools.yaml` + +O reconciliador transacional do framework aceita `type: array` ou `type: list`. + +```yaml +tools: + cancelar_produtos: + description: Cancela um ou mais produtos do cliente. + mcp_server: contas + enabled: true + tool_type: action + confirmation_required: true + requires: [items] + args_schema: + items: + type: array + label: os produtos + description: Lista de produtos que o cliente deseja cancelar. + user_prompt: Informe quais produtos deseja cancelar. +``` + +O runtime pode reconciliar uma frase como: + +```text +quero cancelar TIM Fashion, Aya Audiobooks e Neymar Jr +``` + +para um argumento lógico semelhante a: + +```json +{ + "items": ["TIM Fashion", "Aya Audiobooks", "Neymar Jr"] +} +``` + +A semântica de domínio e a validação dos nomes continuam pertencendo ao MCP/pre-validator, não ao core. + +## 2. Quando usar pre-validation + +Use `tool_policies.yaml` quando a lista precisa ser resolvida/canonicalizada antes da confirmação. + +```yaml +tool_policies: + cancelar_produtos: + operation_type: transactional + require_confirmation: true + requires: [items] + pre_validation: + enabled: true + tool: validar_produtos_cancelamento + fail_open: false +``` + +O pre-validator pode retornar `eligible: true` e substituir argumentos por valores canônicos em `transaction_decision.resolved_arguments`: + +```json +{ + "eligible": true, + "transaction_decision": { + "resolved_arguments": { + "items": [ + {"name": "TIM Fashion Mensal", "id": "1001"}, + {"name": "Aya Audiobooks Premium", "id": "1002"}, + {"name": "Neymar Jr", "id": "1003"} + ] + }, + "target_tool": "cancelar_produtos", + "confirmation_message": "Você confirma o cancelamento de TIM Fashion Mensal, Aya Audiobooks Premium e Neymar Jr?" + } +} +``` + +### Importante para validação parcial + +O contrato `eligible` da pre-validation é global. Portanto, **não retorne `eligible: false` apenas porque um item da lista falhou**, caso os demais ainda possam ser processados. Isso encerraria toda a transação. + +Para permitir resultado parcial, a estratégia recomendada é: + +1. retornar `eligible: true` quando existe pelo menos um item acionável; +2. preservar/canonicalizar a coleção em `resolved_arguments`; +3. deixar a tool primária devolver o resultado terminal de **cada item** em `results[]`. + +Se nenhum item puder ser processado, então `eligible: false` é apropriado. + +## 3. Contrato de entrada do MCP + +Prefira uma única chamada MCP com uma coleção explícita: + +```json +{ + "tool_name": "cancelar_produtos", + "arguments": { + "customer_id": "123", + "items": [ + {"name": "TIM Fashion Mensal", "id": "1001"}, + {"name": "Aya Audiobooks Premium", "id": "1002"}, + {"name": "Neymar Jr", "id": "1003"} + ] + } +} +``` + +O framework **não deve ser usado como um loop improvisado que chama N vezes uma tool escalar a partir do agente**. Se o backend só possui API unitária, o fan-out pode ficar encapsulado no MCP Server ou em um workflow de domínio, mantendo uma única tool lógica para o agente. + +## 4. Contrato obrigatório de resultado por item + +Para o framework reconhecer multi-item automaticamente, a **tool primária solicitada** deve expor uma lista `results` com **dois ou mais itens**, e cada item deve possuir um booleano `success` ou `ok`. + +Exemplo: + +```json +{ + "ok": true, + "result": { + "results": [ + {"id": "1001", "subject": "TIM Fashion Mensal", "success": true}, + {"id": "1002", "subject": "Aya Audiobooks Premium", "success": false, "reason": "not_found"}, + {"id": "1003", "subject": "Neymar Jr", "success": true} + ] + } +} +``` + +Campos como `id`, `subject`, `name`, `reason`, `error`, `protocol` e outros são de domínio e opcionais. O sinal estrutural exigido pelo normalizador é `success: true|false` ou `ok: true|false` por item. + +### Workflow-backed tool + +Se a tool é executada por workflow, o caminho preferencial e autoritativo é: + +```text +workflow.output[tool_name].results +``` + +Exemplo: + +```json +{ + "ok": false, + "result": { + "status": "COMPLETED", + "output": { + "cancelar_produtos": { + "results": [ + {"subject": "A", "success": true}, + {"subject": "B", "success": false, "reason": "not_found"}, + {"subject": "C", "success": true} + ] + }, + "etapa_auxiliar": { + "success": false, + "error": "falha em pós-processamento" + } + } + }, + "error": "falha em pós-processamento" +} +``` + +O runtime preserva o resultado da operação primária e não permite que uma falha auxiliar apague itens já concluídos. + +## 5. O que o framework produz automaticamente + +Com `results[]` válido, o runtime adiciona: + +```json +{ + "multi_item_status": "PARTIAL_SUCCESS", + "partial_success": true, + "metadata": { + "multi_item": { + "status": "PARTIAL_SUCCESS", + "items_count": 3, + "items_succeeded_count": 2, + "items_failed_count": 1, + "primary_tool": "cancelar_produtos" + } + } +} +``` + +Estados possíveis: + +| Situação | `multi_item_status` | +|---|---| +| todos os itens concluíram | `SUCCESS` | +| parte concluiu e parte falhou | `PARTIAL_SUCCESS` | +| todos falharam | `FAILED` | + +Se uma etapa posterior fizer o wrapper retornar `ok=false`, mas pelo menos um item primário tiver sucesso, o framework preserva para auditoria: + +```json +{ + "ok": true, + "original_ok": false, + "secondary_error": "erro da etapa posterior" +} +``` + +Isso evita transformar sucesso parcial/real em falha total na resposta ao usuário. + +## 6. O que NÃO fazer + +Evite estes padrões: + +```python +# NÃO: motor multi-item paralelo dentro do agente +for product in products: + await tool_router.call("cancelar_produto", {"product": product}) +``` + +```json +// NÃO: apenas um approved global sem evidência por item +{ + "approved": false, + "error": "um item falhou" +} +``` + +```json +// NÃO: um único success agregado quando houve resultados mistos +{ + "success": false, + "message": "operação bloqueada" +} +``` + +Esses formatos perdem a evidência terminal individual e podem fazer itens concluídos desaparecerem da composição final. + +## 7. Exemplo completo: vários pedidos + +### `tools.yaml` + +```yaml +tools: + cancelar_pedidos: + description: Cancela um ou mais pedidos. + mcp_server: retail + enabled: true + tool_type: action + confirmation_required: true + requires: [order_ids] + args_schema: + order_ids: + type: array + label: os pedidos + description: Lista de identificadores de pedidos a cancelar. + user_prompt: Quais pedidos deseja cancelar? +``` + +### Retorno MCP + +```json +{ + "ok": true, + "result": { + "results": [ + {"order_id": "P-100", "success": true, "protocol": "ABC1"}, + {"order_id": "P-101", "success": false, "reason": "already_shipped"}, + {"order_id": "P-102", "success": true, "protocol": "ABC3"} + ] + } +} +``` + +O framework classificará automaticamente como `PARTIAL_SUCCESS` e fornecerá ao LLM a instrução de relatar os resultados item a item. + +## 8. Read-only multi-item + +A mesma estrutura serve para consultas em lote. A diferença é que normalmente não existe confirmação: + +```yaml +tool_policies: + consultar_pedidos: + operation_type: read_only + require_confirmation: false +``` + +A tool ainda pode retornar `results[]` com `success/ok` por item para que uma consulta parcialmente indisponível não esconda as consultas bem-sucedidas. + +## 9. Idempotência e protocolos + +Em operações com efeito colateral: + +- use uma chave de idempotência de requisição e, quando necessário, uma chave por item; +- devolva protocolo/operation id no próprio item; +- não dependa apenas de uma mensagem textual agregada; +- em retry, preserve os itens já concluídos e execute apenas o que a regra de domínio permitir. + +O framework preserva evidência; a política de idempotência do sistema de destino continua pertencendo ao MCP/workflow de domínio. + +## 10. Checklist para o desenvolvedor + +- [ ] A tool aceita `array/list` quando o caso de uso é multi-item. +- [ ] Não existe loop MCP de negócio dentro da classe do agente. +- [ ] Se houver canonicalização, ela está em pre-validation/MCP, não hardcoded no agente. +- [ ] A confirmação mostra o conjunto efetivo de itens. +- [ ] A tool primária retorna `results[]` com `success` ou `ok` por item. +- [ ] Resultado parcial não é reduzido a um único `approved=false` ou `success=false` global. +- [ ] Workflow usa `output[tool_name].results` para a evidência terminal da tool primária. +- [ ] Testes cobrem todos-sucesso, parcial, todos-falha e falha auxiliar posterior. +- [ ] A resposta final menciona sucessos e falhas quando houver `PARTIAL_SUCCESS`. + +## 11. Onde o comportamento existe no framework + +Referências atuais: + +```text +libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py + - coerção de type=array/list + +libs/agent_framework/src/agent_framework/runtime/agent_runtime.py + - pre-validation e resolved_arguments + - _primary_multi_item_outcomes() + - _normalize_multi_item_tool_result() + - instrução de composição multi-item para o LLM + +tests/test_multi_item_result_normalization.py + - regressões de SUCCESS/PARTIAL_SUCCESS e proteção contra falha auxiliar +``` + +## 12. Resumo de responsabilidade + +| Camada | Responsabilidade | +|---|---| +| Agente | declarar intenção/tool e usar o runtime; não implementar motor multi-item | +| `tools.yaml` | declarar parâmetro `array/list` e schema | +| `tool_policies.yaml` | confirmação e pre-validation | +| Pre-validator MCP | resolver/canonicalizar entidades e argumentos | +| Tool MCP/workflow | executar a coleção e produzir resultado por item | +| Framework runtime | manter estado, confirmação, normalizar resultado multi-item e preservar evidência | +| LLM/presentation | transformar evidências em resposta, sem apagar sucesso/falha individual | diff --git a/agent_framework_oci/docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md b/agent_framework_oci/docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md new file mode 100644 index 00000000..a032f42a --- /dev/null +++ b/agent_framework_oci/docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md @@ -0,0 +1,252 @@ +# MCP Multi-item — Developer Guide + +## Purpose + +Use this guide when a single user intent must operate on **more than one item of the same kind** through MCP, such as multiple products, orders, assets, invoices, lines, contracts, or resources. + +The framework already provides generic contracts for **list parameter collection**, **pre-validation/canonicalization**, **transaction confirmation**, **MCP execution**, and **per-item result normalization**. Do not create a second multi-item engine inside an agent. + +## Main rule + +**Do not implement business fan-out loops in the agent.** The agent declares the tool and parameters; the runtime owns state, confirmation, and evidence. A bulk operation should be exposed as an MCP tool that accepts a collection, or as a transactional tool backed by a domain MCP/workflow that processes the collection. + +Recommended flow: + +```text +User names N items + -> Router/Agent selects the tool + -> Runtime collects/reconciles an array/list parameter + -> optional pre-validation canonicalizes items + -> Runtime asks ONE coherent confirmation for the set + -> MCP receives the collection + -> MCP/workflow processes each item + -> MCP returns results[] with success/ok per item + -> Framework normalizes SUCCESS / PARTIAL_SUCCESS / FAILED + -> Final composition reports successes and failures individually +``` + +## 1. Declare a list parameter in `tools.yaml` + +The transaction parameter reconciler accepts `type: array` and `type: list`. + +```yaml +tools: + cancel_products: + description: Cancels one or more customer products. + mcp_server: accounts + enabled: true + tool_type: action + confirmation_required: true + requires: [items] + args_schema: + items: + type: array + label: the products + description: List of products the customer wants to cancel. + user_prompt: Which products do you want to cancel? +``` + +A phrase naming several products can therefore be reconciled into a logical list argument. Domain semantics and canonical name validation remain in MCP/pre-validation, not in the core. + +## 2. Use pre-validation for canonicalization + +Configure `tool_policies.yaml` when the list must be resolved before confirmation: + +```yaml +tool_policies: + cancel_products: + operation_type: transactional + require_confirmation: true + requires: [items] + pre_validation: + enabled: true + tool: validate_products_for_cancellation + fail_open: false +``` + +A validator may return `eligible: true` and replace the raw list through `transaction_decision.resolved_arguments`: + +```json +{ + "eligible": true, + "transaction_decision": { + "resolved_arguments": { + "items": [ + {"name": "Product A", "id": "1001"}, + {"name": "Product B", "id": "1002"} + ] + }, + "target_tool": "cancel_products", + "confirmation_message": "Do you confirm cancellation of Product A and Product B?" + } +} +``` + +### Partial validation + +The pre-validation `eligible` flag is global. **Do not return `eligible: false` only because one list item failed** when other items can still run; that would terminate the entire transaction. + +For partial outcomes, the recommended pattern is: + +1. return `eligible: true` when at least one item is actionable; +2. canonicalize/preserve the collection in `resolved_arguments`; +3. let the primary tool publish terminal status for **every item** in `results[]`. + +If no item can be processed, `eligible: false` is appropriate. + +## 3. MCP input contract + +Prefer one logical MCP call containing the collection: + +```json +{ + "tool_name": "cancel_products", + "arguments": { + "customer_id": "123", + "items": [ + {"name": "Product A", "id": "1001"}, + {"name": "Product B", "id": "1002"} + ] + } +} +``` + +Do not use the agent as an improvised loop that invokes a scalar tool N times. If the downstream backend only offers a single-item API, encapsulate fan-out in the MCP Server or domain workflow while keeping one logical tool for the agent. + +## 4. Required per-item result contract + +For automatic multi-item recognition, the **requested primary tool** must expose a `results` list with **two or more entries**, and every entry must contain boolean `success` or `ok`. + +```json +{ + "ok": true, + "result": { + "results": [ + {"id": "1001", "subject": "Product A", "success": true}, + {"id": "1002", "subject": "Product B", "success": false, "reason": "not_found"}, + {"id": "1003", "subject": "Product C", "success": true} + ] + } +} +``` + +Fields such as `id`, `subject`, `name`, `reason`, `error`, and `protocol` are domain-specific and optional. The structural signal required by the normalizer is per-item `success: true|false` or `ok: true|false`. + +### Workflow-backed tools + +For workflow-backed execution, the preferred authoritative location is: + +```text +workflow.output[tool_name].results +``` + +This prevents an auxiliary/post-processing failure from overwriting terminal outcomes of the requested primary operation. + +## 5. What the runtime adds automatically + +With a valid `results[]`, the runtime derives: + +```json +{ + "multi_item_status": "PARTIAL_SUCCESS", + "partial_success": true, + "metadata": { + "multi_item": { + "status": "PARTIAL_SUCCESS", + "items_count": 3, + "items_succeeded_count": 2, + "items_failed_count": 1, + "primary_tool": "cancel_products" + } + } +} +``` + +| Situation | `multi_item_status` | +|---|---| +| all items succeeded | `SUCCESS` | +| mixed success/failure | `PARTIAL_SUCCESS` | +| all items failed | `FAILED` | + +If a later step makes the outer wrapper `ok=false` while at least one primary item succeeded, the framework preserves audit information as `original_ok=false` and `secondary_error`, while keeping the executed item outcomes authoritative. + +## 6. Anti-patterns + +Do not implement a business loop in the agent: + +```python +for product in products: + await tool_router.call("cancel_product", {"product": product}) +``` + +Do not return only a global decision such as: + +```json +{"approved": false, "error": "one item failed"} +``` + +or a single aggregate `success=false` when the actual outcomes are mixed. These formats lose per-item terminal evidence. + +## 7. Read-only multi-item calls + +The same result contract can be used for bulk queries. Usually only the policy changes: + +```yaml +tool_policies: + query_orders: + operation_type: read_only + require_confirmation: false +``` + +Returning `results[]` with `success/ok` per item ensures one unavailable item does not hide successful queries. + +## 8. Idempotency and protocols + +For side-effecting operations: + +- use a request idempotency key and, when necessary, an item-level key; +- return protocol/operation id on the item itself; +- do not rely only on an aggregate text message; +- on retry, preserve completed items and execute only what domain policy allows. + +The runtime preserves evidence; downstream idempotency remains the responsibility of the domain MCP/workflow. + +## 9. Developer checklist + +- [ ] The tool accepts `array/list` for a multi-item use case. +- [ ] There is no business MCP loop inside the agent class. +- [ ] Canonicalization belongs to pre-validation/MCP, not hardcoded agent logic. +- [ ] Confirmation describes the effective item set. +- [ ] The primary tool returns `results[]` with per-item `success` or `ok`. +- [ ] Partial outcome is not collapsed into a single global failure flag. +- [ ] Workflow-backed tools use `output[tool_name].results` for primary terminal evidence. +- [ ] Tests cover all-success, partial, all-failure, and later auxiliary failure. +- [ ] Final response reports both successes and failures for `PARTIAL_SUCCESS`. + +## 10. Framework implementation references + +```text +libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py + - array/list coercion + +libs/agent_framework/src/agent_framework/runtime/agent_runtime.py + - pre-validation and resolved_arguments + - _primary_multi_item_outcomes() + - _normalize_multi_item_tool_result() + - multi-item LLM composition instruction + +tests/test_multi_item_result_normalization.py + - SUCCESS/PARTIAL_SUCCESS regressions and auxiliary-failure protection +``` + +## 11. Responsibility summary + +| Layer | Responsibility | +|---|---| +| Agent | select/declaratively use the tool; do not implement a multi-item engine | +| `tools.yaml` | declare `array/list` parameter and schema | +| `tool_policies.yaml` | confirmation and pre-validation | +| MCP pre-validator | resolve/canonicalize entities and arguments | +| MCP tool/workflow | execute the collection and return per-item outcomes | +| Framework runtime | state, confirmation, multi-item normalization, evidence preservation | +| LLM/presentation | verbalize evidence without hiding per-item success/failure | diff --git a/agent_framework_oci/docs/developer/en/04_mcp_integration_tools_and_policies.md b/agent_framework_oci/docs/developer/en/04_mcp_integration_tools_and_policies.md index 146418f5..d5d433e6 100644 --- a/agent_framework_oci/docs/developer/en/04_mcp_integration_tools_and_policies.md +++ b/agent_framework_oci/docs/developer/en/04_mcp_integration_tools_and_policies.md @@ -82,6 +82,31 @@ projeto_multi_agent_isolado/ ### Main components + + +### MCP multi-item: product, order, and resource lists + +When one intent must operate on several items, **do not create an MCP loop inside the agent**. The framework supports `array/list` parameters, pre-validation with `resolved_arguments`, set-level transaction confirmation, and automatic normalization of per-item `results[]` into `SUCCESS`, `PARTIAL_SUCCESS`, or `FAILED`. + +The complete contract, `tools.yaml` / `tool_policies.yaml` examples, MCP payloads, per-item output, workflow behavior, partial validation, and anti-patterns are documented in: + +- [MCP Multi-item — Developer Guide](../../MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md) + +Minimum structural result from the primary tool: + +```json +{ + "result": { + "results": [ + {"subject": "A", "success": true}, + {"subject": "B", "success": false, "reason": "not_found"} + ] + } +} +``` + +Every item must expose boolean `success` or `ok`. For workflow-backed tools, prefer `workflow.output[tool_name].results`. A later auxiliary failure must not erase terminal item outcomes. + ### Simplified HTTP contract used by the project ``` diff --git a/agent_framework_oci/docs/developer/en/INDEX_DEVELOPER_GUIDE.md b/agent_framework_oci/docs/developer/en/INDEX_DEVELOPER_GUIDE.md index 7dfff1e7..b803ac5c 100644 --- a/agent_framework_oci/docs/developer/en/INDEX_DEVELOPER_GUIDE.md +++ b/agent_framework_oci/docs/developer/en/INDEX_DEVELOPER_GUIDE.md @@ -27,6 +27,7 @@ If something is not working, use **Search by problem** below. | A tool does not appear or cannot be found | `tools.yaml`, MCP catalog, discovery | [MCP/Tools](docs/developer/en/04_mcp_integration_tools_and_policies.md) | | MCP Server does not appear in the catalog | registration, manifest/discovery, MCP Gateway | [MCP/Tools](docs/developer/en/04_mcp_integration_tools_and_policies.md) and [Gateways](docs/developer/en/05_agent_gateway_mcp_gateway_and_auth.md) | | Parameters sent to the tool are wrong | schema, mapping, BusinessContext, extractor | [MCP/Tools](docs/developer/en/04_mcp_integration_tools_and_policies.md) | +| I need to run one operation for multiple products/orders/items | array/list parameter, pre-validation, single confirmation, per-item outcome | [MCP Multi-item](../../MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md) and [MCP/Tools](./04_mcp_integration_tools_and_policies.md) | | A transactional operation executes without confirmation | tool policy, `require_confirmation` | [MCP/Tools](docs/developer/en/04_mcp_integration_tools_and_policies.md) | | A name search requires an overly exact match | parameter extraction/mapping and agent logic | [MCP/Tools](docs/developer/en/04_mcp_integration_tools_and_policies.md) | | I receive 401 between gateway/backend/MCP | Basic Auth, credentials per hop | [Gateways and Auth](docs/developer/en/05_agent_gateway_mcp_gateway_and_auth.md) | @@ -73,9 +74,9 @@ If something is not working, use **Search by problem** below. ### [04 — MCP, Tools, Policies, and Parameter Extraction](docs/developer/en/04_mcp_integration_tools_and_policies.md) -**What it is:** reference for tools, MCP Servers, mappings, policies, and parameter extraction. +**What it is:** reference for tools, MCP Servers, mappings, policies, parameter extraction, and multi-item calls. -**Use when:** tool integration/execution is incorrect or needs to be created. +**Use when:** tool integration/execution is incorrect, needs to be created, or must process item lists without parallel logic in the agent. ### [05 — Agent Gateway, MCP Gateway, and Authentication](docs/developer/en/05_agent_gateway_mcp_gateway_and_auth.md) diff --git a/agent_framework_oci/docs/developer/pt/04_mcp_integration_tools_and_policies.md b/agent_framework_oci/docs/developer/pt/04_mcp_integration_tools_and_policies.md index d9c1c522..d9942074 100644 --- a/agent_framework_oci/docs/developer/pt/04_mcp_integration_tools_and_policies.md +++ b/agent_framework_oci/docs/developer/pt/04_mcp_integration_tools_and_policies.md @@ -83,6 +83,31 @@ projeto_multi_agent_isolado/ ### Componentes principais + + +### MCP multi-item: listas de produtos, pedidos e outros recursos + +Quando uma única intenção precisa operar sobre vários itens, **não crie um loop MCP dentro do agente**. O framework suporta parâmetros `array/list`, pre-validation com `resolved_arguments`, confirmação transacional do conjunto e normalização de `results[]` por item em `SUCCESS`, `PARTIAL_SUCCESS` ou `FAILED`. + +O contrato completo, exemplos de `tools.yaml`, `tool_policies.yaml`, payload MCP, retorno por item, workflows, validação parcial e anti-patterns estão em: + +- [MCP Multi-item — Guia do Desenvolvedor](../../MCP_MULTI_ITEM_DEVELOPER_GUIDE.md) + +Regra estrutural mínima do retorno da tool primária: + +```json +{ + "result": { + "results": [ + {"subject": "A", "success": true}, + {"subject": "B", "success": false, "reason": "not_found"} + ] + } +} +``` + +Cada item deve expor `success` ou `ok` booleano. Para tool baseada em workflow, prefira `workflow.output[tool_name].results`. Uma falha auxiliar posterior não deve apagar resultados terminais já executados. + ### Contrato HTTP simplificado usado no projeto ``` diff --git a/agent_framework_oci/docs/developer/pt/INDEX_DEVELOPER_GUIDE.md b/agent_framework_oci/docs/developer/pt/INDEX_DEVELOPER_GUIDE.md index eda78895..67d0cfa8 100644 --- a/agent_framework_oci/docs/developer/pt/INDEX_DEVELOPER_GUIDE.md +++ b/agent_framework_oci/docs/developer/pt/INDEX_DEVELOPER_GUIDE.md @@ -28,6 +28,7 @@ Se algo não está funcionando, use **Buscar pelo problema** abaixo. | Uma tool não aparece ou não é encontrada | `tools.yaml`, catálogo MCP, discovery | [MCP/Tools](./04_mcp_integration_tools_and_policies.md) | | MCP Server não aparece no catálogo | registration, manifest/discovery, MCP Gateway | [MCP/Tools](./04_mcp_integration_tools_and_policies.md) e [Gateways](./05_agent_gateway_mcp_gateway_and_auth.md) | | Parâmetros enviados à tool estão errados | schema, mapping, BusinessContext, extractor | [MCP/Tools](./04_mcp_integration_tools_and_policies.md) | +| Preciso chamar a mesma operação para vários produtos/pedidos/itens | parâmetro array/list, pre-validation, confirmação única, resultado por item | [MCP Multi-item](../../MCP_MULTI_ITEM_DEVELOPER_GUIDE.md) e [MCP/Tools](./04_mcp_integration_tools_and_policies.md) | | Uma operação transacional executa sem confirmação | tool policy, `require_confirmation` | [MCP/Tools](./04_mcp_integration_tools_and_policies.md) | | Uma busca por nome exige correspondência exata demais | extração/mapeamento de parâmetros e lógica do agente | [MCP/Tools](./04_mcp_integration_tools_and_policies.md) | | Recebo 401 entre gateway/backend/MCP | Basic Auth, credenciais por hop | [Gateways e Auth](./05_agent_gateway_mcp_gateway_and_auth.md) | @@ -74,9 +75,9 @@ Se algo não está funcionando, use **Buscar pelo problema** abaixo. ### [04 — MCP, Tools, Policies e Extração de Parâmetros](./04_mcp_integration_tools_and_policies.md) -**O que é:** referência de tools, MCP Servers, mappings, policies e parameter extraction. +**O que é:** referência de tools, MCP Servers, mappings, policies, parameter extraction e chamadas multi-item. -**Use quando:** integração/execução de tool está incorreta ou precisa ser criada. +**Use quando:** integração/execução de tool está incorreta, precisa ser criada ou deve processar listas de itens sem lógica paralela no agente. ### [05 — Agent Gateway, MCP Gateway e Autenticação](./05_agent_gateway_mcp_gateway_and_auth.md) diff --git a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/runtime/agent_runtime.py b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/runtime/agent_runtime.py index dbae2498..2ec6be62 100644 --- a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/runtime/agent_runtime.py +++ b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/runtime/agent_runtime.py @@ -1351,6 +1351,101 @@ class AgentRuntimeMixin: # Compatibilidade com versões antigas do router. return None, arguments or {}, None + @staticmethod + def _primary_multi_item_outcomes(tool_name: str, result: dict[str, Any]) -> list[dict[str, Any]]: + """Return explicit per-item outcomes for the requested tool, when present. + + The contract is intentionally structural and domain-agnostic: the framework + only recognizes an array named ``results`` whose entries expose an explicit + boolean ``success``/``ok`` signal. For workflow-backed tools, preference is + given to ``workflow.output[tool_name].results`` so a later auxiliary/composite + step cannot overwrite the already executed primary operation. + """ + if not isinstance(result, dict): + return [] + + body = result.get("result") if isinstance(result.get("result"), dict) else result + candidates: list[Any] = [] + + if isinstance(body, dict): + output = body.get("output") + if isinstance(output, dict): + primary = output.get(tool_name) + if isinstance(primary, dict): + candidates.append(primary.get("results")) + candidates.append(body.get("results")) + + candidates.append(result.get("results")) + + for candidate in candidates: + if not isinstance(candidate, list) or len(candidate) < 2: + continue + normalized: list[dict[str, Any]] = [] + valid = True + for item in candidate: + if not isinstance(item, dict): + valid = False + break + signal = item.get("success") if isinstance(item.get("success"), bool) else item.get("ok") + if not isinstance(signal, bool): + valid = False + break + normalized.append(dict(item)) + if valid and normalized: + return normalized + return [] + + @classmethod + def _normalize_multi_item_tool_result(cls, tool_name: str, result: dict[str, Any]) -> dict[str, Any]: + """Preserve partial/full success of a multi-item primary operation. + + Some composite workflows execute the requested tool successfully for one or + more items and then fail in a secondary validation/post-processing step. A + wrapper-level ``ok=false`` must not erase those terminal item outcomes. + + This normalizer never invents business semantics. It activates only when + the requested tool itself exposes two or more explicit item outcomes with a + boolean success signal. + """ + if not isinstance(result, dict): + return result + outcomes = cls._primary_multi_item_outcomes(tool_name, result) + if not outcomes: + return result + + succeeded = sum(1 for item in outcomes if bool(item.get("success") if isinstance(item.get("success"), bool) else item.get("ok"))) + failed = len(outcomes) - succeeded + if succeeded and failed: + status = "PARTIAL_SUCCESS" + elif succeeded: + status = "SUCCESS" + else: + status = "FAILED" + + normalized = dict(result) + metadata = dict(normalized.get("metadata") or {}) + metadata["multi_item"] = { + "status": status, + "items_count": len(outcomes), + "items_succeeded_count": succeeded, + "items_failed_count": failed, + "primary_tool": tool_name, + } + normalized["metadata"] = metadata + normalized["multi_item_status"] = status + normalized["partial_success"] = status == "PARTIAL_SUCCESS" + + # The requested action is considered operationally successful whenever at + # least one explicitly identified item completed. Preserve the original + # wrapper status/error for audit instead of discarding it. + if succeeded > 0 and normalized.get("ok") is False: + normalized["original_ok"] = False + normalized["ok"] = True + if normalized.get("error"): + normalized["secondary_error"] = normalized.get("error") + + return normalized + async def _call_mcp_tool_uncached( self, tool_name: str, @@ -1384,6 +1479,7 @@ class AgentRuntimeMixin: ) result = res.model_dump(mode="json") if hasattr(res, "model_dump") else dict(res) if isinstance(result, dict): + result = self._normalize_multi_item_tool_result(tool_name, result) result.setdefault("cached", False) await self._emit_ic( "IC.MCP_TOOL_EXECUTED", @@ -3839,6 +3935,21 @@ class AgentRuntimeMixin: "Resultados MCP normalizados pelo framework:\n" + self._compact_llm_value(mcp_results, max_chars=18000) ) + multi_item_summaries = [] + for item in mcp_results: + metadata = item.get("metadata") if isinstance(item, dict) else None + summary = metadata.get("multi_item") if isinstance(metadata, dict) else None + if isinstance(summary, dict): + multi_item_summaries.append(summary) + if multi_item_summaries: + sections.append( + "Semântica operacional multi-item do framework:\n" + + self._compact_llm_value(multi_item_summaries, max_chars=4000) + + "\nOs resultados explícitos por item da operação primária são evidência terminal e " + "devem ser relatados individualmente. Um erro de etapa auxiliar/pós-processamento " + "não pode converter itens já concluídos com sucesso em falha, nem omiti-los. " + "Quando houver sucessos e falhas, descreva o resultado como parcial e informe ambos." + ) transaction_evidence = self.transaction_evidence_for_turn(state, mcp_results) if transaction_evidence: sections.append( diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc index 4beeadf8bb927e731c26c3ba132adb123a6e6c40..c90b9cf5fa785d7488f4ae3767bef3dc9a7f22f4 100644 GIT binary patch delta 27 icmbQs+{!%Rmq3JmZeEFgN@7W(eoB6_q4{Jb#%chHJ_%p| delta 51 zcmZo=p36MpmqvkpZeEFgioS2KXM8|WepYI7NwI!*Qc9A3VtQ&`NqlmCUP)qcywPMX G#%ciU$`Y;s diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc index df240730d9713d6519f56ec19c71dcc3ea4efce0..29dcb1a69e921869732878eeb786a7e523d0d275 100644 GIT binary patch delta 20 acmcaBa94o)GcPX}0}$9hSiO-uhywsY#|7O0 delta 20 acmcaBa94o)GcPX}0}!a1uHDET!~p<383h^u diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-313.pyc index a526262e0cc97fd03683e032cad60442143b03a6..49e7eeed7380e6291bf62cdd206baa7141659b09 100644 GIT binary patch delta 29 kcmccQy32J#AhSTUer{fgeoA6VqJBz#vZ49rO6Ev;0HuBkK>z>% delta 53 zcmdnxddYP|AhSlXer{fgeu}b>KSU)={C28|4w%@h@BBBoQ delta 55 zcmZqcWSrW`xS@zmqd-45uS7pZ-#6GZKAb>KSU)={B}qRqJvFZ+J~=iWIg0 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc index 6f06afb7404b9c9ad19e6f549edb8b1200c2ec39..736d34bf9f8415efd21c103af500acd62f71368b 100644 GIT binary patch delta 17 YcmZ3=GL2hyi<6?CML-;{oK3~{SW&9|7|u>k-Va}Kfq delta 53 zcmdlfd_s7`CMJzm{oK3~{SW&C<-5838014o3h0 delta 53 zcmcc5`HpkLXC{q${oK3~{S*5lH~(P@V*vn3vIi>w delta 27 jcmX@icZqMqStiEn$>*5lIg<19N)n6XjW$1Hie&)+mpTee diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-313.pyc index 1350a17013ea5747224bf6467943cf46c2d156ea..53839a5e05f1ebaec5d3d47ad9f7af8c6c9d7884 100644 GIT binary patch delta 38 tcmX@@wa05iBco)ger{fgeu} delta 53 zcmdnvb=qq~Bcn!(er{fgeu}9FJ2?GF00tZ9@ delta 27 jcmZp+nq;-%CkJEGb>KSU)={B}qRqJvFZ+J~=4X%nLW diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-313.pyc index 26bec0f695209f64e41c27f7c7cd0460babb9c51..3ac254ef372328edd8a04761f0360be781a7a1a7 100644 GIT binary patch delta 14 Vcmcb`c$#s79b?u+d-;jExd13>1v>x$ delta 23 ecmX@jc#Cm@9b@H0dwGuJ{JfIH;&`Kp;UxfL*9cqy diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-313.pyc index dfc8266ec4d7245cd87882c4e80015cd1cf35c30..24e30c3c99f30fce37546ead91663f8ffb3443ac 100644 GIT binary patch delta 18 acmX@7uwP-r4JO8{$v2tgH?uRl^8x@!R|a7K delta 27 jcmdn5a86;v4JO9Q$v2tgIg<19N)n6XjW&N|^5X>nn~Vy9 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-313.pyc index 0f8134e45ecd7bc2df933e78a5a033c9c3358c98..d2b66476276a908f6c139941ba30d5181cbaf64b 100644 GIT binary patch delta 18 ZcmZqU`_8+;m5DKJvKy29<`Sk!EC4!x1+V}B delta 27 icmey)+s3!Sm5H%*vKx~;M{<5%Nn&xl(dIa&nJfT)UI@_u diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-313.pyc index b7058f90786bda4ece0bd87e5c96ed147c1e5384..8e6f6ff81dd4ead87400343aaf1592bdfdfaaebb 100644 GIT binary patch delta 18 acmeCx{im~G6+2_*vp> diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc index c4eeee9d76df595b78d9b1d1814033c6dabc8b21..7292b69cfeb61eb8563b360b7e337ca2c4e55f05 100644 GIT binary patch delta 38 tcmdmGwAyIHLMF*P{oK3~{SW%_o@(#Q+!34m|(> delta 53 zcmZ2&w99D2LMDw`{oK3~{SyvL&-TM{<5%Nn&xl(dIyAb0z?BvV#{kqR6D diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-313.pyc index e874174f70f7924874a98ac3cabf68d361ab7078..f71ef5ce9d382be87e55c4e2e4c35bc5b7b67ae1 100644 GIT binary patch delta 20 ccmbPxg|Y7n;|4uu#;VEs%<`LKnGd7^08$_aPXGV_ delta 29 lcmeCX!Z`N|;|4uu#?Hz5%<>$``FSOY#qma)-IM!lWM5|a&DG4S!~s171_}TG delta 27 icmbPcw$yBc4>M!!WM5`^j^zBjlEmV8qs^(z8^r;ELV=aMr{oK3~{glL#ME#WfWJB}K+}g$50LQ%xWB>pF delta 53 zcmaEs^Dk$^V=awx{oK3~{Sb%7 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc index b7933581bca688eb729e0ee31860acfa1f8cffed..c8b2c65c7c7356e8d8641207d9528bd5fcd1a3a9 100644 GIT binary patch delta 14 VcmdnOw3KN=FJsokKKY4zDgY^<1?d0) delta 23 ecmZ3=w1sIxFJtAzK6#Gh{JfIH;&`Kp%jyAW0tpHL diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc index daa4d787ff6ab344eb8d679c4045c930b0b21e2f..b7440582be04b84d4af576bb16a7916b11034781 100644 GIT binary patch delta 38 tcmZpZ`YyTQGNWXPer{fgeu}eV=>79~Q>y$$weoIg<19N)n6XjV6n-?gjvpY6>m@ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc index dc2c8ddee836ab76e4513e332ce0a1b119fff4c7..3707422ab34c19fe499473a4a7383f52805b93e6 100644 GIT binary patch delta 18 ZcmaFJb%|?(1QTP%WJxCZ&F)N6%m6sz1mOSx delta 27 icmcb_^^j|W1QTQVWJxA@j^zBjlEmV8qs@j)ip&6dQV0S7 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc index f1aaec9a44b7fefb91e4db01c597bd9cded42e8b..347747a814c1185541f709d1c0659ce74d13f2f9 100644 GIT binary patch delta 18 ZcmX@*zT16+HxpywWFIE^%~ebRiU31X1|t9f delta 27 icmdn(e#(7=HxpySWFIDZj^zBjlEmV8qs=Ky;fer@RtZD^ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc index 271e5d608e427c98d452e3ee972c1761260b9850..e7d688715a742140670e96e945efd049ab6611f6 100644 GIT binary patch delta 38 tcmdm{v|MRJA&X>zer{fgeu}oLu4c!0$ delta 53 zcmZ3kv`uM4A&W-6er{fgeu}YQT09zlkxUU#tkz$8QUk%;*{q|&d)1JERHwYyopoF833`M3ikj2 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc index efdc67dbe678fbb689961c902c4e7907b021e74a..0a7ca94657c6d5bde914f9e1f3fc62bcae114548 100644 GIT binary patch delta 18 acmZ3gH%)KDJZ8q+$@7`zH=kvW5C#B4R0f#< delta 27 jcmbQHw^VP#JZ8q4$@7`zIg<19N)n6XjW%y*ju!?1jK2xG diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc index d945f0b1cb6a1294d997365d2112f746ed44630c..40bb9186b3f3034e9aef7fa9ad160efae3d9b3bb 100644 GIT binary patch delta 40 wcmeyem+|Rd#tlr|lBN2&c_sQO`o6)Q@c~8oS*gh-#roMvDM_2PxK9NG06_c?IsgCw delta 55 zcmaF5m+{M9#tlr|8ZG*{c_sQO`o6)Q@c~8oS*gh-#roMvDM|W?>8W`o@yYplC5grH LMw_L%PXz-2Rs|IQ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc index 7c280a45c0b19ffe13f54791fe0e13d85c527397..bc72ad3f70b0266b7d4b36c0573e60d979d7162e 100644 GIT binary patch delta 40 wcmaE{it*+u#tnh2lBN2&c_sQO`o6)Q@c~8oS*gh-#roMvDM_0vS>O8u079-0uK)l5 delta 55 zcmcb)it)uN#tnh28ZG*{c_sQO`o6)Q@c~8oS*gh-#roMvDM|W?>8W`o@yYplC5grH LMw_!(-}?gqSX>o! diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc index 9408e0b7f18f840e08f53d754e144cc9f75c0ada..7149a33f880080a8b64f72270733a4f2d962e85f 100644 GIT binary patch delta 18 ZcmeAU{S&g`9W!Ij<{9 delta 26 hcmZoG6SGExer{fgeu}L+2l8GW;?MG0BOt#Y5)KL delta 29 lcmaF!fa&)GrVTA@j1`kx+2lEr^Ycm)i{p(p&t*Hm5&*;+42u8& diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc index 365d13c077e08b89d33a49870d14aa40247daf61..fa19d80451df62530f25abe356d2b5f0e4786e41 100644 GIT binary patch delta 18 ZcmdlYzEpfeG$&*EJ1He;b0n)4GXMhT4DbK| delta 53 zcmew&&@8yYkX2)RW`svqfeD2PldsB8pH3wtoz|%-8^rdj^zBjlEmV8qs?_3lSKfAl?iPC diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc index 9b2f632da982b4a35ce1c0948dc76ae7cc118730..8517b365a54d3d253c6c567519052b34c6729241 100644 GIT binary patch delta 18 ZcmX@$y3uum4KriKWLswW&DqSM@&G`r1?vC+ delta 27 icmdn!dcbvq4Kri=WLsu=j^zBjlEmV8qs^hrG4cS18VL*l diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc index 78b3a8c5d7b2175b1155894428cdc6a5aa0d2e3e..87cf9fbcfad925d465ddb80b4cec90bfb4f002db 100644 GIT binary patch delta 18 acmcbSb24W`7AIrVi_^x0|$lx delta 27 jcmX?^b0cR%7ANDx$=RIp9Lf24C5grHMw^>CkLdsao#6_n diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-313.pyc index bb720a1c8a77a49272111ad708494151b1ddec92..19e28320439611bbe9cc80dfa45d8a241b0396fa 100644 GIT binary patch delta 18 ZcmeyK^df14fdFIqWJ3Y@&G7;fiU3Or23i0B delta 27 icmaEn^gU^VfdFIMWJ3XYj^zBjlEmV8qs^WI@`?bLX$gA( diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc index 81bdd67008f0ad51137b0af65c4ad3e00d143245..b4566fed0263b7b825c939189b810bdb8e0c8657 100644 GIT binary patch delta 17 Ycmcc3e1>_06eDB(WNAkE$)1dp05eYoHUIzs delta 26 hcmX@Ze4BZL6eDBbWNAiuj^zBjlEmV8qshjMGXZgx2v-0A diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc index 6bc38dea756c9989838583ecca74b0775397fed0..90abefbc0c259983502e6502d775813895251711 100644 GIT binary patch delta 18 acmeyU`$%`geip|1$p={EH@{qFV}b diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc index e80e85dc224f55966a2c7560b48ff76c1df8f6ef..4df9c40846cbb3577e630c7a024e1d4fec02048d 100644 GIT binary patch delta 18 ZcmZ1uwP-rH9p4v$=CVhIg<19N)n6XjW)mMb7TYnn}!O0 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-313.pyc index d4050835f379bd07cf562e567843f55f7aa7f8b4..097df85db727a15ba29a73cbe103144662dfdf75 100644 GIT binary patch delta 17 YcmbQm)y=hmgN3nfGAE1tWOJ6s04nwbpD87y&=o1+)MF delta 27 jcmeC;o5{D~7As@lsgiZcQLk0%M# diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-313.pyc index 2c3791e9e4c2922bba01ca3559367d6b70cc9416..eef8446fd24cab7c4d74c705849654cfc866a794 100644 GIT binary patch delta 20 bcmey?$@sjJaYL&-WBueddHKy-ii~vWH28#dy delta 27 icmX?Nec5_LoDAc{$?-Ds9Lf24C5grHMw`oJd>H|gA_=Sj diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc index 702a1c147f5165a8469b7c42941e9c2f5ece4cf8..e9494bd2abcf1e63ca8775c4ef5042a3dbf2357c 100644 GIT binary patch delta 20 ccmccK!FZyBal=a|#^%Ydoa8r4INLJ<0Aj%iJpcdz delta 29 lcmX@n!Faucal=a|#z~W3ImvS*=jW9q7RMWHW^#681OUK+3tj*K diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc index e1602bd0bead516489b03edd3aa209458ba1434d..a25fe0a20799a8bbbf2dd27b2d21e064decbc6ef 100644 GIT binary patch delta 18 ZcmaFmc-wJ9t2|@%WDRC{j^zBjlEmV8qsoaY16kGcLy7$R9 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc index 4b93a35023a8a90eceff04f127846a27131ef8e2..f3df8b2b09079cc830a66b8ca6bd7fe72c7f004c 100644 GIT binary patch delta 17 YcmZo;{m!zXhLN#qaxJ6$n+a delta 26 hcmey)(#E=>hLN#zaxJ4gM{<5%Nn&xl(d4O&j{tpv37P-^ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-313.pyc index 2a99c447c7928fe866b41723bfb676fcc89a6a6e..981a1b21d7e3e4ace6e5635d1b79218c480de573 100644 GIT binary patch delta 18 ZcmZ3)KAC+(4ijU? diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc index 9feeeb4e04c70a10c2a3a47a0321a09a370087a3..e5d55be2621b13cb9c306524d35eab9c0d7d47dd 100644 GIT binary patch delta 18 ZcmZ1yHZ^R6oj7CTWP5S>&AH;+g#khk26g}d delta 27 jcmbOlwj^wWojBu!$@b#%9Lf24C5grHMw`RM_Xz_4iIoYL diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc index 3947485cef5ebc839a48ef4791c51299cd5e0b24..7586e9bcb3582fed1461d8ad8816124419d2dbb5 100644 GIT binary patch delta 18 acmca8c}Q}@8CJ%c$!A&RH~(h6#s&aPy9d_* delta 27 jcmX>kc~Nr18CJ&b$!A&RIg<19N)n6XjW$1Jy~_pwo2v@= diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc index f46198f478a099fa00b01754cd964961baf838c7..3a37461efee62bf0878cc2373be5971e6fe3c063 100644 GIT binary patch delta 18 acmZpb`X;&IJS$`EW&72(myZ|L<4b}hv delta 53 zcmX@9bwg{zLw1cW{oK3~{S7k0*)$zR#!H!E}4@&W))#Rmic delta 27 jcmcbp^+0RG7k0+($zR#!Ig<19N)n6XjW+XgxbOl1qv;AI diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-313.pyc index 57ba0f7a708c4f1807b6b5957583a86a71608b59..1f1da75465b276b33019fd0f1c4171ae36975c41 100644 GIT binary patch delta 18 ZcmaFvaKm8(n;>JwWOhOM&8C7z`~X1G1%vKRWOhM$j^zBjlEmV8qs{Vymiz#Q)Ci>j diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc index f48f21d49c43955fa2b9f5a97e70ad0f1b9239de..398ae9a440a2229c7da19c02247e1064806278bd 100644 GIT binary patch delta 37 scmbQv(!sJJnNhMJ1He;ayMfS0PD*Q5dZ)H delta 52 zcmeBRna;8ynNg!hKR2&LKSkd+*fTz$C_gJTxujS>J1HeeKQTQuuOvP>Kd&UQINoS- H4Py@g-~AHS diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc index 738af6c8e05297296b25bb99d1c91c97a55f3bf3..8e5fdab25c9aa7f1a68c827cb3a5d10c95b5645e 100644 GIT binary patch delta 18 acmcc3cZP36E-Pd8xdr9` delta 24 fcmeBXp2a-j17qdHkMbPJ`FSOY#qmayIT@P(cWDU+ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-313.pyc index c2ca0e7533534d8399fe64f3a78e1dc76e67c8d4..7f3406d0749a18cbf1049132041d7279e235a650 100644 GIT binary patch delta 18 Zcmcbna$IGDFEeA#WIty4%{9!o_y9qo25lv0Gw86SHK7er{fgeu}V!Z diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-313.pyc index 03c55fa72c5ae596d477d4311edce450ee0c1c27..99332fb1cf8218ebc6429c371f6d3d995a9a14a0 100644 GIT binary patch delta 18 ZcmaE@az|xD95Z9q*p>95Z9(;M3axC%J{ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc index 04d6239795dc9c3606e20d6a3136cbd263f17f86..6a632a9c68f1aa906bbb75d908666ef1bf52a456 100644 GIT binary patch delta 20 ccmca~o$2s(rVV{;jH#3R+2l9xWfNTr0AdUXX#fBK delta 29 lcmX?no$1nbrVV{;j3tx%+2lEr^Ycm)i{p(pFK3fk3IMrg3yJ^$ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-313.pyc index bf49c5979a47dce055acd252abcb936e65b8e152..22069715710dc2130c002c4293bb00b6a89a4447 100644 GIT binary patch delta 14 VcmaFNc!hC-9b@rCd-;jEWdJFg1z!LF delta 23 ecmcb@_?U5m9b?l(dwGuJ{JfIH;&`Kp;k5u|{0M*m diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-313.pyc index 08fc703bd848abcc4fe8682ac273a72072f71ef0..fce729e1ac76699559606aa646c3562a801ee290 100644 GIT binary patch delta 38 tcmbQI)vvXIiAAzhKR2&LKSkd+*fTz$C_gJTxujS>J1He;vlh!20RZ@h4L<+? delta 53 zcmeCzny0maiAAGDKR2&LKSkd+*fTz$C_gJTxujS>J1HeeKQTQuuOvP>Kd&UQINoTp IG|LwO0P)Ea1ONa4 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/__init__.cpython-313.pyc index be306050e0f4620d050608474792ecebfc772069..2ec04b1116f8433737393870fe1fd63e8b05e6b8 100644 GIT binary patch delta 14 VcmaFOc!zO<9b@%Gd-;jEbpR@>1%Chl delta 23 ecmcb^_?mHo9b?x-dwGuJ{JfIH;&`Kp;jI8?W&Aa$k3jhEq3l8Q0 delta 53 zcmca+_tb8~BtDHU{oK3~{SB(XT&Xz~>1Hvn@I2|oY; diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-313.pyc index 3cb62fd0831d3fb04035e75a29a1e9a33d945891..58f0f6cadb842eeb84830d9f1ee0e4c1f1096dc0 100644 GIT binary patch delta 17 Zcmeyu@|0ym4kKgv{oK3~{Sj(*^@p#ier{fgeoA6VqJBz#vZ49r_snLJ0H(qUo&W#< delta 53 zcmeCRT57f7II~8rer{fgeu}&#}703I_F>;M1& diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-313.pyc index c48d691bcb17a20c5b69d812f936702828273ade..de23ebc1bf30e54bb1672283a98e76a023842d10 100644 GIT binary patch delta 29 kcmeyv`Gj*rGqXUXer{fgeoA6VqJBz#vZ49r)y#p60H-DjSpWb4 delta 53 zcmaFD`G<2uGqXmaer{fgeu}_0DI;U*WHUzj$tjHG05qHhQUCw| delta 26 hcmX@Ze4BZLDI;UaWHUy2j^zBjlEmV8qse}ZbpUhT2y*}c diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-313.pyc index 0fcf8a97bf0cf5f59be418a9c1000b9e414daef1..d6725a6b4c40c030904280a3c6253990c3403a4f 100644 GIT binary patch delta 20 ccmey<&-k{Val;yB#^lLsndLX%W>$0o0AO?oB>(^b delta 29 lcmaFc&-kaGal;yB#-hn^Ycm)i{p(pA7$2X0RXpj3q}9{ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-313.pyc index 20a34108bac849e9dab90e4c879a18810c95d508..24583c526074507dc97d67ac70cec3f6e40fbaa0 100644 GIT binary patch delta 38 tcmca5a9UtPFq34mer{fgeu}ta7$oAFq1}+er{fgeu}o{2GavI3L*WEfZtLDK5s0$)~yGH~-`+(*XclF$j17 delta 27 jcmaEm_dajKDK5tH$)~yGIg<19N)n6XjW$2#s?`Aiu(=DF diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-313.pyc index 6a7f80bcd768d0cdcc03da35a8b51e818c5ad44b..a16a8d559022810eeeac6b6a39eab709aae7294f 100644 GIT binary patch delta 28 kcmey!ag$@i3TAid|7zI0XD{_$p_iwIg<19N)n6XjW*w8d(8v@n0N}% diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-313.pyc index 9f8133b7581babf65520f27f2a99d4cff66c6392..9236ac0cc4456ba42790e7d7e2426e0b1c486c74 100644 GIT binary patch delta 18 ZcmdmKy2^BeD-&bEWH%=H%_U5(5&%9D1-1YH delta 27 icmZ2wy3=%nD-&b=WH%;xj^zBjlEmV8qs?(lJ`wv$dXVg&$1Ee1yb delta 27 jcmX@kdyRL)R7S@7$ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-313.pyc index b8449b8f52e57f5f71bb86bffd4be7c7d3c20a7a..b7f02d74be523d4d4ea37bb14dc2960c801c74ac 100644 GIT binary patch delta 29 kcmZ4KIMHzfCzC*$er{fgeoA6VqJBz#vZ48AL#7Hj0F>AXegFUf delta 53 zcmbQ}xYBV0CzD25{&$i1K0AFzkLjV8( delta 29 lcmdnBoblvx#tjcx85<`*WR>Sg&d)1JERHwY{FC*dF95vT3}XNQ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-313.pyc index 1b693ec78627c83f5564aa6290682a22970969f1..cf881877ba5e8b5f3c08aecc78165940712041c2 100644 GIT binary patch delta 18 acmca(dDe2nH8#e)$=BKBH?y)|7X<)L$p=vY delta 27 jcmX?WdB<|YH8#fD$=BKBIg<19N)n6XjW)k$yC(_&r34Fc diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-313.pyc index 88fdd0d5ebc5728da6d8a59d89aaa93a6d45fd15..c11c2cbe4c5fd1effdfef94089229d9e86b83459 100644 GIT binary patch delta 38 tcmdlavsh*WGmB(_er{fgeu}_{zUQmyxl2vL2)S<`~8mYyddr1&#m! delta 27 icmey$-y*OTt>!%$@3WHC!b+l4gf(t2KN8} delta 26 icmaFD@|k7BTt>$F$@3WHIg<19N)n6XjV5nnTn7M&^a>aN diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-313.pyc index 7aaf3326e5348a14706faccf92ec94ceb93e8bdc..f4e9539a49612bc94d6d51b538811778e5a105a3 100644 GIT binary patch delta 18 ZcmZqS{>rsMo{_P5vI3+0WvI3(#M{<5%Nn&xl(Pj%qTNVI!6$k?W diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-313.pyc index e13ae8310d1fb929c2ff99558886a4aecf787f14..96d1455b6ee33081ce15fa9788e3fdbe74eb9533 100644 GIT binary patch delta 18 ZcmaE=c1>-A7c*nkWN&8q&6Uh=_yI&l2C4u6 delta 27 icmcbn_Ec?y7c*n$WN&79j^zBjlEmV8qs__8pZNidE(yy3 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-313.pyc index 6a7b77e246e7c49247bac172ac7e6b5be3a7aaf1..b9496669348f9e9b7a7cc1d29eefa9649e434cdb 100644 GIT binary patch delta 18 acmew@_C{>OT1Lj=$?F*9H{W5L&j|oc%Ljh| delta 27 jcmaDO_FHVjT1LjE$?F*9Ig<19N)n6XjW!=+T*e6ioU#g_ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-313.pyc index d9233affb3f2cb6002c6092289396057a636cdb8..758ed3520ad355efa290a5602fbdcb066b3befe3 100644 GIT binary patch delta 18 ZcmcbjepG#fFB4<&WIrbP%{5FBf&f761@`~| delta 27 icmX@AenowQFB4mbyaG^RyM|}$=lfEIg<19N)n6XjW(ZSt6&2Fmg@>i diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-313.pyc index 209e518930f35da9d2c0ce8ea47e51716bb25c55..fe43eb8be7d6f901757d43161009ff0d56916955 100644 GIT binary patch delta 18 ZcmZ3(H*lX>4v<_+5Hj0KZ**yT4zu@@f&08p<7NB{r; delta 29 lcmdltllkmS<_+5HjP;Xs*yTBr^Ycm)i{p(pyRcUs1pu7n3TXfU diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc index 374c66c0fafa53b8121bfb40c23a25c58b8f1b19..75197bad90eb01434db52fb1fb6bceedb9fecf54 100644 GIT binary patch delta 38 tcmez3{M31aBd27cer{fgeu}>Ah4nP0^ delta 53 zcmaFr{Ka{LBd11#er{fgeu}8W`o@yYplC5grH LMw_*nj5h)RWJ(nl diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-313.pyc index 47ffce896306e071f6e5b7216f58dd016475f9c8..ab3f0dea13eb4b0f5c1a7d97f99f3f674860e106 100644 GIT binary patch delta 29 kcmZ2eI;C_&KBGW}er{fgeoA6VqJBz#vZ49r>5QV50ILNGZ~y=R delta 53 zcmbPIx~6nPKBGp1er{fgeu}{oK3~{S=2k`#5db-F1yuk5 delta 27 icmeCuo~gYdjFGW?ayX+rM{<5%Nn&xl(dK+cX%PT?YY27# diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-313.pyc index bdfb59699bef8ad559da69c4fec801cea320093a..5d5cb937d5a30868e77bbe47a2ec505c9d451bae 100644 GIT binary patch delta 18 ZcmZ3MG(Bm93^QZ$WLakU&ECwnbpbvA1`q%M delta 27 icmbQ9v@B_Z3^QZVWLai;j^zBjlEmV8qs^wwk8}ZnrwK6t diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc index 72b822106729185a4460e4ec597b84217ec72e2a..56db068703da9c93a4d929060e9e36b3691cb5ad 100644 GIT binary patch delta 18 acmeCJ{8zDIDI;U%~wiuJRTQj#`HF&}pY07_jCZU6uP delta 55 zcmcaKk@4X~#tomCG%ECS^Gftn^nHUp;{%HFvr>~wiuJRTQj+u&(^KB(XT&XtN`ey*vPU1PDq1 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc index 96c6acb132e92eca605f994a7ddc2722e1ad9f9c..803e56ff7207335f91187d3ac82dd56c71274249 100644 GIT binary patch delta 17 YcmeBV{l&83DkEd&@~ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc index f8c401b745b7a5c3f0ce9f3f31cb8c5c6d470733..7480b74c43d726235c990c44154fb1f6c1588242 100644 GIT binary patch delta 24 gcmZo^V*T34y5Th+W6|U{eDcjw{M)7Y8DAL!0DFN5_W%F@ delta 33 pcmey`$lB7xy5Th+W8>sEeDWO0`FSOY#qmbXEd1M9_!&PM0s!F{3<3ZE diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc index c6302b5f9daed58130af6444fce9d37d8f25f9f1..ef67a44b455e6c5f6427c119e79331122c289e72 100644 GIT binary patch delta 38 tcmbOr+$g-kkXbTaKR2&LKSkd+*fTz$C_gJTxujS>J1He;b0o7l8vyZw4153p delta 53 zcmZn^o*=xzkXfTlKR2&LKSkd+*fTz$C_gJTxujS>J1HeeKQTQuuOvP>Kd&UQINoTp I7qdAV0O(H=K>z>% diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/multi_intent.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/multi_intent.cpython-313.pyc index 4e496180f12cd23961b9b46a30bb32934a5a674f..a25f733287f39faad11df164bcdbe684d80f7cf4 100644 GIT binary patch delta 20 ccmZ28k8$oi#tnJQjJcEZndLXnW$yO|08%OkXaE2J delta 29 lcmbO`k8#aB#tnJQj5U+^Ycm)i{p(pw=+-k1^}Rz3W)#! diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/pending_topics.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/pending_topics.cpython-313.pyc index 4054cb7367c64c9c1c022a5bdeda59da6e2c4f7c..09c217755d29ec98e053a4d7999a671cbe879620 100644 GIT binary patch delta 18 ZcmZpx`(C?&pP4a#vH-LEW;^B+)&N9I24?^O delta 27 icmexf+g7)MpP8|4vH-I@M{<5%Nn&xl(PjHvy?3SlKABOypqJ?c%z9Y F>Hz9b6S4pR diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc index 61dadcc3d9dbf487bede12c43b15d7b51a6f8cff..c23d6d16a51840a9dc3599f6d70e123491136822 100644 GIT binary patch delta 14013 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 list[dict[str, Any]]: + """Return explicit per-item outcomes for the requested tool, when present. + + The contract is intentionally structural and domain-agnostic: the framework + only recognizes an array named ``results`` whose entries expose an explicit + boolean ``success``/``ok`` signal. For workflow-backed tools, preference is + given to ``workflow.output[tool_name].results`` so a later auxiliary/composite + step cannot overwrite the already executed primary operation. + """ + if not isinstance(result, dict): + return [] + + body = result.get("result") if isinstance(result.get("result"), dict) else result + candidates: list[Any] = [] + + if isinstance(body, dict): + output = body.get("output") + if isinstance(output, dict): + primary = output.get(tool_name) + if isinstance(primary, dict): + candidates.append(primary.get("results")) + candidates.append(body.get("results")) + + candidates.append(result.get("results")) + + for candidate in candidates: + if not isinstance(candidate, list) or len(candidate) < 2: + continue + normalized: list[dict[str, Any]] = [] + valid = True + for item in candidate: + if not isinstance(item, dict): + valid = False + break + signal = item.get("success") if isinstance(item.get("success"), bool) else item.get("ok") + if not isinstance(signal, bool): + valid = False + break + normalized.append(dict(item)) + if valid and normalized: + return normalized + return [] + + @classmethod + def _normalize_multi_item_tool_result(cls, tool_name: str, result: dict[str, Any]) -> dict[str, Any]: + """Preserve partial/full success of a multi-item primary operation. + + Some composite workflows execute the requested tool successfully for one or + more items and then fail in a secondary validation/post-processing step. A + wrapper-level ``ok=false`` must not erase those terminal item outcomes. + + This normalizer never invents business semantics. It activates only when + the requested tool itself exposes two or more explicit item outcomes with a + boolean success signal. + """ + if not isinstance(result, dict): + return result + outcomes = cls._primary_multi_item_outcomes(tool_name, result) + if not outcomes: + return result + + succeeded = sum(1 for item in outcomes if bool(item.get("success") if isinstance(item.get("success"), bool) else item.get("ok"))) + failed = len(outcomes) - succeeded + if succeeded and failed: + status = "PARTIAL_SUCCESS" + elif succeeded: + status = "SUCCESS" + else: + status = "FAILED" + + normalized = dict(result) + metadata = dict(normalized.get("metadata") or {}) + metadata["multi_item"] = { + "status": status, + "items_count": len(outcomes), + "items_succeeded_count": succeeded, + "items_failed_count": failed, + "primary_tool": tool_name, + } + normalized["metadata"] = metadata + normalized["multi_item_status"] = status + normalized["partial_success"] = status == "PARTIAL_SUCCESS" + + # The requested action is considered operationally successful whenever at + # least one explicitly identified item completed. Preserve the original + # wrapper status/error for audit instead of discarding it. + if succeeded > 0 and normalized.get("ok") is False: + normalized["original_ok"] = False + normalized["ok"] = True + if normalized.get("error"): + normalized["secondary_error"] = normalized.get("error") + + return normalized + async def _call_mcp_tool_uncached( self, tool_name: str, @@ -1384,6 +1479,7 @@ class AgentRuntimeMixin: ) result = res.model_dump(mode="json") if hasattr(res, "model_dump") else dict(res) if isinstance(result, dict): + result = self._normalize_multi_item_tool_result(tool_name, result) result.setdefault("cached", False) await self._emit_ic( "IC.MCP_TOOL_EXECUTED", @@ -3839,6 +3935,21 @@ class AgentRuntimeMixin: "Resultados MCP normalizados pelo framework:\n" + self._compact_llm_value(mcp_results, max_chars=18000) ) + multi_item_summaries = [] + for item in mcp_results: + metadata = item.get("metadata") if isinstance(item, dict) else None + summary = metadata.get("multi_item") if isinstance(metadata, dict) else None + if isinstance(summary, dict): + multi_item_summaries.append(summary) + if multi_item_summaries: + sections.append( + "Semântica operacional multi-item do framework:\n" + + self._compact_llm_value(multi_item_summaries, max_chars=4000) + + "\nOs resultados explícitos por item da operação primária são evidência terminal e " + "devem ser relatados individualmente. Um erro de etapa auxiliar/pós-processamento " + "não pode converter itens já concluídos com sucesso em falha, nem omiti-los. " + "Quando houver sucessos e falhas, descreva o resultado como parcial e informe ambos." + ) transaction_evidence = self.transaction_evidence_for_turn(state, mcp_results) if transaction_evidence: sections.append( diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc index 4758e940d7689f4c44d92180adf3f58c424bae66..5ac50c81998768d0172c06869df0191163c415fa 100644 GIT binary patch delta 14 Vcmcc0c#Ls^9b@W5d-;jE82~501t$Oi delta 23 ecmX@cc$IO29b?HvdwGuJ{JfIH;&`Kp;rRe!rU*y? diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc index 61119b566612ee11762b72e2fc85071c7dbd6751..11389d3a5f9cce05d2401ae1addf4150296bb5fe 100644 GIT binary patch delta 38 tcmezB^~`Gn6N_ZBer{fgeu}{oK3~{glL#ME#WfWJB}Gmzd@O0GZfJ1HeeKQTQuuOvP>Kd&UQINoS; IBC`M!008_FrT_o{ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/input_contract.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/input_contract.cpython-313.pyc index c3276735f770b2116ad5b29505804ac46d556a09..f61ef43e3a7f4bbee33c436528f8ec04b79b9875 100644 GIT binary patch delta 29 kcmccNa=>N7PG*4&{oK3~{glL#ME#WfWJB}K51Gs50JB63MF0Q* delta 53 zcmX@$a>HfAPG*e;{oK3~{Sh($ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-313.pyc index 0dbba318bb15f6fc0377e97e77b56b0ed1d6fcac..145eccfafe4a80ac524e3c6a521862d8373ff839 100644 GIT binary patch delta 29 kcmdljv{-1vRYrj%{oK3~{glL#ME#WfWJB}Ke;MuA0i-nwg#Z8m delta 53 zcmZ21v|DJyRYr{}{oK3~{S(*OVf diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-313.pyc index af17ba4ba7e36da03ef11cd1a4af1d82b6861fd7..6003c0c1af3cbff85c8bdb5a6baf9bf1a89d093d 100644 GIT binary patch delta 29 kcmbOu+9JB)38O%Yer{fgeoA6VqJBz#vZ48A9;OK#0Gx#h!2kdN delta 53 zcmZn>og=#838O}her{fgeu}8W`o@yYplC5grH LMw=^`S9JmaKJOI# diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc index d68fa0052ec4336ac2477968688b1dd13dc15e55..a3ed0b063515b82520ebc64728af76b9b97aab5b 100644 GIT binary patch delta 29 lcmdnMKZAe6GDd-P{oK3~{glL#ME#WfWJB}K=NKQc0sx)13bFtI delta 53 zcmbQizkz?lGDeMh{oK3~{S/judges.yaml --- + +## MCP multi-item — não implemente loops no agente + +Se uma mesma solicitação envolve vários produtos, pedidos ou outros itens, use o mecanismo multi-item do framework. Declare o parâmetro como `array/list`, use pre-validation para canonicalização quando necessário e faça a tool MCP primária devolver `results[]` com `success`/`ok` por item. O runtime preserva sucesso parcial e produz `SUCCESS`, `PARTIAL_SUCCESS` ou `FAILED`. + +Guia copiável e completo neste template: [`docs/MCP_MULTI_ITEM.md`](docs/MCP_MULTI_ITEM.md). + +> Anti-pattern: executar `tool_router.call(...)` em um `for` dentro do agente para simular uma operação em lote. Se o backend só expõe API unitária, encapsule o fan-out no MCP Server/workflow. + ## 3. Pré-requisitos ### 3.1. Requisitos locais diff --git a/agent_framework_oci/templates/agent_template_backend/app/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/templates/agent_template_backend/app/__pycache__/__init__.cpython-313.pyc index f6a2b79f0ac62dab88b9458890c4272746a21aa0..a252d88c086e11d4b5acd82de80fe9bd82d1c3a9 100644 GIT binary patch delta 60 zcmbQpxRsInGcPX}0}xc-SUr*3ST#gHH?KrLC9xz?KP5le&|E(;JvFZ+KCLJ*H?=&! OC_6qsIa7b4eGmXNNfa9Z delta 24 ecmdnWIFXV2GcPX}0}ya#7fj?fW;B?X90UMG76p|6 diff --git a/agent_framework_oci/templates/agent_template_backend/app/__pycache__/main.cpython-313.pyc b/agent_framework_oci/templates/agent_template_backend/app/__pycache__/main.cpython-313.pyc index 08f8cb6c796a90e7306597eb22f68a0d4d0fce17..d63c5001e1d1cb5032bbd3da1a46737616fbb9c1 100644 GIT binary patch delta 2731 zcmZ9Odr(u^9mns<&Ar@&@DK=(7)SyHk|=~Xk*5(97B%Y@tKh20BPa*~Z;%AE8(+Iy zZCyvt%$9XKyRb7Y*qzqebZk4FwrfYXzP5&DDUVidckS5O-L~1Tf=p-J{(fg?J3Hl% zPrl#p@0@eb{hdQ5*WOUPJfVpFEG9RRpno*{deeRK0OZCm7l zUU%n^*S^1_tHU1rUZNvjp-d0n&-w*V+|+5#qc(FYjT9x*f;??dW!aZVZ z__B^w{`pcu_m`N7#KzWF8Tp-%)RyR}p(L07pgfuEqF1U+!tUnSQU(22X*#V`sp#X< z6z!gZ|E<;Bo-Z_ag|j#N(woh|2^yXbRvBdx93Ob*l2HO~dcC9Xl^8f4t+ zRTw!h?}_uoc5{$KyLK`r0M)Lmj6*<`>k8vrK*@EF@iHT2JjS>V80CsE-emj{TVLVP zv(-hHPvY_$MD`HTwFZU=t`5d}pwjg@<0c^Q+QrDxZ`Dqc?qKoSol)5d-h+c~dAP?r zAh*eG@4>zy??PPrUbklm?cjjN>-N%D8cfP)xqUDFenTr&HC~Pv<%iH~`6a|DK=7T$ zF|@i!~Q&A}aK1PMaIDI3m$#G@LebyfPAlI+oL##%+-})bX5FKep}7 z9k1<}iVCL}L{?y!Kt>r~D~+XY*w^qH`& zY1X#odPgJ$OR1bTXMA{abYe7AR2R;zpUw4L7w@QVs6)+r!;SmEhWb2_G#skqwCQ8r zZ}z^{JCz#FD2lAaP|sX^!FEnA8 z$!S+jZMfKUp(#|pE!46jy!!b_78bI(;x#|BU9yF$Tf;>=<}8j`OWm}kE^JvpXQ`gc z$Y%R6gfrI6Wm+a}6SfddYH5kF!_-ezS*fw#Y<$#6M_Tri2Ku*_Kg8}KTx!{0HP6m# z{GYB@(rc|nfl-c}$Qv%;E|K9plEYuK5?`8l&6WZB zU5WVg;=3xQb9Fw0^gBU`j1iHE>&jrzO%?H(#hYrU2F$Hw;xi|0uz`^CVo+zOR<2N zt0jJwIM3l*&1Vq5Mw~a`)8@@-{y1^IrrrSNUOMq7N%t~%)Fz$3Lbz8+{3+7CDl_Q& zCgRsg_cQC#z7Om{|sd5}%~S<(aZy3zo+hdScVkshwBD+Keg zhWM@0$1zR=m`_#{|7z)zyoM4mk6>xL^eD3o^y5_GFOnXoSwSxFGuEZ`Z<`Ta{T(n>p7V`+4@?wG7m&h*$Dw2G${8Fp{W+_n#<)t(N)0Xs% z25jV#h3Qp{`HY2(C5+{a6^zx$Cmexwp72bIj4DPAV;r{hNeY4OKG6l(2ecH7kui%g zhtbLiO@OMMv52vRv5YO}U=OPhM^>noIWoe>E)xyv7~J}DQZ#I3*+51zmCHsEb&fbv z9kslgjMz2Hc^V1Lny67OxV-Ztp8PxbU{9`sJf)h>UkNVwcKdtq_nj{(^j45orThwh z{hdKLA&}3a+C&Gt^}-hLV(@HtlY-RHKksXZuEzoE5gTZJPu{L|D4P%)0oHhV1y24N z1~rIg#8yNB7S^KLhWN@tXtyI;5MNo5{=6qcXoWC3_@|zi6_ygLPs2Las4td_!k`!z zR)Ja&y88}#_sO;NRG(Sc4T&N6)4q#JVx?UN9O7pAnKp$9@+@TmN4{>uj?4vz{0kk$v! z4Lb-qKyUfd1uq0!ga7b}MDT%Z4LB}*qnNmG?jd^jcm+8ZOg-^WWfPAv zyA*|3W2eZrTZ{HT2sI2@5IWmC_qo5gV|auMs&-F%-^fr;r&q4VQBUcXlSw6wxEw{# zZu1f=^jf}@2W7B2qrHuVskOn+$?qT@#!5U^&ERX?tGZeh|+peI1^>RU~ h>K~xbo)XFJ;I>mdFODjSJ~A3?JAIvy0JWS+|1VUV{VV_g delta 2536 zcmZ9Ne@t7~702K8^Lu^<;}DE7ar_g4jS1mr_>BQWlh8zQlhR}X(ojku!Qq#l!4I-f zH_flAS<`NJP3bhX@W%>KrKRbUx=qujNlUt|O%)hn1ZyK}lc`e^teSzx%9AyFZ0cI(Z+QOj zK7oGLmP!Y*Eb49VdnWqxs!dc=T`T+`pDWSOqt*Gm?&%6T(PNd`NK?x`Al*}Hp|6(d zsnu^0TT2Mkr_QZ)^j<|8IY=+~-Q-#NKJXCDD|4FK3ZM?|f#aH<%M+T~^LVPQxg$J( z;Ac%8^nOh*$)GK@d!ySWZigY5222co9oD$GFyFVX&)CH=M*~a<{+cnwXa(wnM;IG{ zQt&k6LBfA^5@*htD!yEE zsV1(+IDs>Jr?boBi5M6-bH;d8JPEatGrPxg;_FZ+b7tGv{&!m5YMIi_+6&_A(M*YQ zX8TyzJE6BiQ|YsgqPPj&RL-0=-ZdGT2u&9TW4{ zS2}_#3x*5#%$1^e5#5uF*w&w06A4CuIu5{ze zjZ5|Px6Q{$fO=d0YHT4~dg*6|rxpyu528HPwH8H(J>>M3p)~Fa88T@<(1QB#2@cGw zrDUjDyjsSiuFM}c@Yj4~s8+m|;{g4UL?RmTBR$hzYebO#BxsRIBGOb}3WGk@lSrcY zaYDcV!6#`XViZ5I1d<`R?j@1+;`Qu6N))0`D@i0({In{dh2RFCh0JBabODK2#OXpe zSTiXkVijjh4I%_LH;{;3ylKq=J*OoRmpCWjyty0_$rR@{>rfXNVDED^B;pb0Y6Z}L z)B3@mCnVw%=QV*;2%@)OU%BEfOEv_zYDpwtT;TAj791o}BrZ5{wS}w=krHvC<_RYR zi*^#JlolO4YPVH!35!)E;+Gbyvq0Z=6NQs*XEbbp;PWb?@Y3hiF3@*uL=mMs_J9t8 zyPJrjm+ofOmqa1@!b%i_^u@-8LI~~|h_X()mlSY9a6gwQDboEd+i{tPI-;1Rhf*o( z8lt324{Lp(m$Hdsm6m*1c&Pw;y;MyUo3!M|el8R2!g3N(9OAMOyRd8`aLUVR2}2e9 za@3VNw3T1pDqv8d#dIx!X)78=0UNnuWO_YgDx-zb%4lbFF=jG)2-I2eF`dhp&sfA* zf-PO~6WH!57iAwjqsXXdgf2jO9b*cknK7La8U|S#mRoh;VyiAuDbufdh~hJ@dJU+H zaqFvN#**6%LcSC|# zXOHaEkSgj3?MMvZym~|f9SCiCwie|ML?ghLEU(9!PoYtT*n`-MD8PgtRTJWSg)n>u zu@CXRiuCJ{L)Z_dq}q?2(_|N7eg^9JbdSqv(J02kBB+?q)iV@6Dp%9%y;(vlI5u^q z_p+9F=(}>c7{_rB=v~=MEYuKAFJUVQSmF@QPLTVD20PmZdfNMB?3a84Cp?Gh52$(( z?X)@Enb-xU7k>1@uM!$lwyKZ9PxIf^-=`cGdLSQAZz|=4^wFddyD$L8UNwJ2B*Gxb z{c7d$2|^t7??22Cj)T!k`4h{M0n{ZTJAX3j6{4Vz(%jLp#1o+8QN#=M#^@&DC6K*z zZPZO(RIM-kgODY<7HtrIgd^0t7dwgL5$^O`#6^IQm(RdQOz7$E?H-iV=^syeh1X&9 z3H7U!sf6gL_Efp>Q!q}_z^S(#Z(yOrIQtj^FNMrJ#98|2)SzVyhXf%3cWMmt2N7fR z<ySc07;+kP#EYX}_- zi3uI;9Y;GK-!wePn7+NQy=P>wyCW?7anv`68kXsj`+M6)+IxHCZCIURhTZ%nRCwSq zZFgT+zg$gBV05C(E+)IDH8l20`7tNX+>IH0i`aW0<4u(DTE(;j{oz3wZ-In`1Kyopx z!4i`l8HFeRW7M1M#>mGl1D0h0ipzq;8RaJDGfFbbgV_oowx}Xl1t(C25}c(Bk{47# zGg%d^OATy-I+)Y|lbRq>UJI<6ErulqgxO7)K<YCx{hh1;bEl9ASj z%NW3A3?Zz^jm*NzAU!5JKaIkar1L#5k?m7qQvygpIFiu!}t@^Q}asVi&BdV^7D#Qi*NB2q~@h$=B3A% zb>KSU)={C28_njzGq_lmBy^p1hs&QJkpc z43!zh3!Gv#3sIZsdC%XNP8YwoFx z-jf@7bipPUc>_%@@&OsoVUwGmQks)$SL6@mG6He27?AkD%*e=ipF!~pn>nNE1jz-e KpBaD*us#4;6lewj diff --git a/agent_framework_oci/templates/agent_template_backend/app/agents/__pycache__/billing_agent.cpython-313.pyc b/agent_framework_oci/templates/agent_template_backend/app/agents/__pycache__/billing_agent.cpython-313.pyc index 4e27b2050509f616535e4eeacb5853c87efd3d19..527b98eaa722e3a9d9db6633654e9868d259da51 100644 GIT binary patch delta 1019 zcmY+DO>7%Q6vyZ7uDxr!UgM8AaqM6dJBc?Rc5-l2t7=1qQ7K{5sKx>mq3zb*lx?w1 zXE%b-L-;t*6Clln!lBKnNPyZZNQhe_AkLvhj(ljeP^nxvaB^CTgb)(5n;OJO`wFV67!|+0Il#o{T|+MZ~Vo4zyVL*Koq_-d2ZqW=E6R&U}} z<*`@o4s<;Ydgm5vn3$aM-+=EnSaF?Mi;vzPOkR;LOIM%k3{LIFhOWde$9_%@UoBiK zt{2-=M?2}cyJ_WCp;g>0ZZCD7d4;O>t4b$%dN+~X^SFn^KfGxA@W&@UxwsRaxW#mR zbg7Hni9lCG*{N%*>#OaV=R0Hbd+|WX+fATA_^vp5joSX!QIJKhH8)G+?Smi(x$W5!P;vVZ$Pw;#k*BeA zhi;F;9hXDFq0gb{Fz7HsN&XJL6I!Hg84N`#h5P7)pC%uL#^4h9CUgNxL<;AEShm-r zHeT9y=wa3U8n~j5UL@`CJe($p$iQTk=Iobb(8q(iECAd?hwq{3-`yn!4z|OYN5~HF H08Re`AO8go delta 640 zcmYk4O=uHA6vyXnW|M5}WK?qV*BnBG~Y8tbNU_eMw zL{B|9H*LY5%t3_^FJ6R#G=*F$JqRHMZ(ftsB3{IqErJ8@H~;saHy_N*`}p^;bSR1@ zM4NE$!QD-{Eu}b^Cspp9*-Xu+G!6%RC#-vpN!#GY`I!Vy-Wcb=PX@*r2)q;IO-jfWj41bq#t#~8 z8jg(a4n!iIf$)i&JykB1D{7-~yRup@J*pSVrFwCtST9C+)kpVNJq#{}2t$&@L_hRN zPP_&uJ1ubn$QS7YlsYxb78ec0-!`@yd&#B!kTNnGWYh2jvRJ=K(XUdpmD-n*Ly?*< z^h23!$kk?(;|0@LLXPYh^P)6f0u;CeBP@v0$ccm`g?t4@Hj`lbU0bKyKXE8=cm;|B zzhqiWj?iVJUh7JW3?;Xv`?9o<=$bOWIHaW}~7y9=NMaW|WxdN&POC5(47 z=bSX_O@I=`J=wtY6fn9pdNukr1~rB?Mkz_px+Y(s$EtA@9*=5gH*|*Fw1r@eJhN5l z)Bmz1p9Sm%VzHz=>S$TNBw4h$6Df7fK6vyYS$KJIUudxkjVkgAdB-jb@heQZ2B5p+xpX)?57D5&>i@gbk#xAoP zm5&2e%YhS$G#pARm5&QmIkd>!xHvt;Ie?VN2OA^g!O`Va~r!`-{(D=ufanZCA@6*B!%oaNiI6^u}3YnG40IKoBq%HVSqm4L&?Fm|5+bjyeSuIcb?_i*|`w?R@mqIRDD|% zXNKsk(37yF`vkPll6En2=@*QUo;NvZa>ArvKxzMoWfCIM>asA!Wo)Ig&VG8+r77i- zUb>(b^QH1nGkViLqp2jXtLOA4ieQpp%`~m%0yRagGD8aLnkh`Hx>8hhrO6j6tkyZ5 zj*7krPl9X)2^cVzg+vTQ8JZ$drt(D9W`5K)lB5+eM6ZcQ!Bc%Hy1`y%i{G?pI-&2^ z{R_3~UFToiC4c{OU+;~`^~lZr4d2jmSI>>E>s?QJgExooByS}bhejKr)Z^g@^8(zjb~w zaj>!V(2C#XakRRT%llXwSds?*9&Shpd#i_yUa_@;R9k=c(zwNHcdSaNGqsAXPHFWZ zpuWSfitSAMkUhcR8HbfE4!h%>c9nhdubpxS`~ink_)kMsLFVxNL8j(ab}A+@P7Q?d;gg?46{4_G$9{Kk_piz zKB(WHQP$;?988ls_s(Xf#V0flzw!u$Q2@O}WJ7RuiiUfb1bC+ungq5Hp@ndUC*SxG z`6P@%gzO7ph?3vJm^t>(am`PHqRs3-_9JvjAVJ;FSeG9VMzR0OvIkh&qCujQ-Ej}~$6;e=^+ii{)O+y*E^Fz!_@^BVV^gIl(D9Hm4 z60;P_JPhn6(e$hFf{uUeR@3kbR5xB_sspMQe;B7~!w;$tZv=`Vnrw2Q2Jxn$z>;nh z)Clgzn7?}l)EMsOb5w6lL0(PZt=w4;&9+BDP2p{2glR7@`g8_$Ms&t>CUmAKN!_-h z%+PB!IEp|(bFddWML2s5R!Gvm45!JeJ)`vSVx?BqoUA){Z0Xr6#v8ypkBX$=P~kFp m?r^8C(jNOE4G%@%000MQ`T$M*Fg^m9+EKzshzZS2+kXK_PMKH$ diff --git a/agent_framework_oci/templates/agent_template_backend/app/agents/__pycache__/product_agent.cpython-313.pyc b/agent_framework_oci/templates/agent_template_backend/app/agents/__pycache__/product_agent.cpython-313.pyc index 104fb209ce4a99b382d87c8eeade62720bf96d77..b29b8b8bb5b208bc26942547f8640417dee96600 100644 GIT binary patch delta 1745 zcmZ9MOKcNI7{_Pq^=s|eiQV`W$4;EY@dH1S;6O?sq$Gk6NYWY?s;F|8c%g>a4zp`W z$^mFEtyHN+a{$@{L8?R~Dpgf_=%EL4DCKd$)=Kqi%Yk01o+>AZK5m`a)RfkefBSvk ze&2uovpe>m;Twb2XDux(AfJo!oipD#zqY0|i9)hi5|jDl(acnC4wcXF3!;!bdoq7A z$(`m)V(t{;iu{E#I-4sm6q0yC^QF0kD11P^&)i0wu>03NTBjCQ^e*VeMSTD->ZjDq zM>E)|(yub0vWwEuorcs20GVLITry?B8xU_A9EP4O%$hR2_$#dw+w?B{vEF0}Z+8MN z2>>m++%JavUOfQ-=LO(}K5(Cp+G@*GlGLkiBq6qtlbNT=Ecn*Eu};j%u2d1Ju#uUlrDSAQV#EPJpI8o$_OCp~~A>s;W*!VF- zx2x!Qgvv`1oR0))#(E!CDPOv`H zpYK!i>I963J;+Yywv*h=up~e6CPhs)&lI zBJe0D^2?$EA`IG1L=~NS@)fgCuAl{e`=+tTi(H-)ImNJ0CR)oPzGL=A3@Au#bWzYV zf+7@Y0>zBD(>cTol|@lN`|%TVFVPZxZ7W(qL<)1VTwaV=FlxyS&_Ogz zr`zZ>f1dsVm$;S1GM86~1wkOz1a(cpLfX3UZ!J4CE6lpjx&bdeb@$fY;hHW)n&<eHua+Nk8+{XfkNu20p?p_)0g zHd>GEsm1nudq|2+-uFtejBIyai(ie)t%Gta(=NAm(OK2d057FR;(S&0f~T z{w3TZFZg};91A~#vnl3t8m+_GA?BMHi8caoc9_}dnh28Qo(9g2F!!_vtR#8R24_c^ z2ljD>BoCc%c8q!Gav!Hj63%IuhpAm8e$)@=bj+jh1SHAh2%IxAkD~?}52=-5l_M%g zRgO_sH7a!~jfA+}e%XGUI2Gu>Y*!a*Cl_=O-?sO|YxuGK9Gu4Ejzk+eM(a+B+;+zm y2dBRPb9&f=r5cB*tU_ delta 1000 zcmZ9LO>7fK6vtr!EQyihv`Ui}C4jRuYGVw7s!A4OP+M## zYazJVv2$jXob2b2srp1wl{w|P%RLy9;XAe5F=8& zOaq`JwCs>`Fvp@D&X15Y ziZ}z_BA<=qco7_>vi(@ZqD3a?Q&Mp6SoW~)$boqeddl=5g%80fn&b~p4eaMXg8Snv z;YJaVRrfPr^zBsuAV>W__7i&u2GL_)^ZeIH)0u1xwfWvbYVHXOPEd2}HrFuW+yV>c z{>AnR+XHNJn!W_%@#?hjIixHVjk|le`I*!6nVB;)(`e(sa5PR^2|R%{NHBzP-Dh6T z7c2U*Ra&}wv7%e%3x#~eTrw+W++iu?aD*UC5GNQ# zA9|v28-3|H2fft|j}JO8luB3P0{X+d(5n;45sYoNkS~{U%d%aiOui-h$~Q#i>FRCY zCR}R?!KM(Z3!$GgO+l>-YD)^-9{zE-hRLAP-SS@{`p`L7MN1Ix@uBB_^ znT9soQuL;htSia;6Ak6#j*Ib0Z61X5whweg+JNg4-vQ1oVh^Jmc)FTmye`Jq2O8o? zlO3tCBRlBU!Nr6&ba(a6YHf73p&1>)CGqV8wm4B26YHslINEmO;4NocLd*V@wKdAY z@w+0Br*;{KTil(6VBi$&Ft|&n8*rl-(r2)9kmvY+%0J*2{#G`I;IGh-ncs+4g+_>Z zIEcN?K4^rQ&B(NZH_s?&^fS-sPsnC#02)zdOC|cPNoc6d)>In%&&S}D5o4aGk9FhS z3m-HR%nQjy{17Az+w8X)wW->S*-T)fjlfOmI3BA^E=43_`SHUVN131oZ=#jp3chxK z1$AkgDVl}66(HG9_ausJIv1fM@OBz~FB{!wNmM2vCAQg#0{*A2 MttQ{r~^~ diff --git a/agent_framework_oci/templates/agent_template_backend/app/agents/__pycache__/prompting.cpython-313.pyc b/agent_framework_oci/templates/agent_template_backend/app/agents/__pycache__/prompting.cpython-313.pyc index eda48f56cae61bf11461b26c11974f94f0c0418c..e8484aad65b8561ae9442e426e70b73ee2e9acb8 100644 GIT binary patch delta 63 zcmeyyF^iM?GcPX}0}xc-SiO;3fLS$0KR2&LKP9mwQ9mU=+0a}+F+DY}BtESuF*mh5 RzbHFCKRHu>vkY?-BLI0Q6o&u+ delta 27 hcmbQm`Hh47GcPX}0}ya#7i{DfU}m(~?7$qw2moCz1_1y7 diff --git a/agent_framework_oci/templates/agent_template_backend/app/agents/__pycache__/runtime.cpython-313.pyc b/agent_framework_oci/templates/agent_template_backend/app/agents/__pycache__/runtime.cpython-313.pyc index df7bf1540128d98ce4730c2b8fec5005d9603a10..5ed22f0bce1951dcd6fb6061aefd987797323133 100644 GIT binary patch delta 232 zcmcb?bdj0&GcPX}0}xc-Se-RvBCjN)+eCF$wP1!|W^Xnx_9Au#h8T7w22+p{AW&e? zX9#8rWGv!HXVGMx7~v_W$#_e=C^bE^xFoeGz9c_CC%z~(FD11owW!!nlXKz{D<6Tx zf&#sQqSWHlypqI{%>29}cA!bO*yH09b8_P2S2BDCnS3isKR2&LKP9mwQ9mU=+0a}+ zF&(HOKCLJ*H?=&!C_6qsIa7b)dq+clplU`SE|v!pAD9^#8SgSEedl0c3}d{=5PFxv UY03>2TzyJUM delta 112 zcmcb}e1nPiGcPX}0}ya#7i4)%onGO@^$*-w*w;!P_- z_W1b3oSgXhl?G05qx!n@Yu4Ye3DSZ9@RX;h?Xhn)iqq)I#N*=bt!N&fiv=llEW z`C0F7c(;c?u-k2jtZO?@=l*a%=Le}+HlE9C@l0Guj*C-DVNOnKYJC1u=2BdmmGhc7 zqewaVYC)M73+ZeepP_!`J|Pab$aAo2DgH;@rh&nEHqf3z=a1{=AFt_8>v;-rm1*(? z2cT9t1>twCObbE*RO>?spQF9ej=CzvCOczvim7WQ8lhxYis^$%=tE~94z)RZxIU4L z#2DOa?!bRC9_Yq@GePLlJ^k-Jr-SeJMAfIJgLs%7b9`{=jnT;{UNw16q|712qA}A% zhd~D+HSrH2Ol%mOF*s$=$D#?}kZA@YvEmzcp2}OYd5s)o#i2_1td{*z&WPFkGJ7sNw$4K zEc-9+w1)SrmNx##hWbw49slLpOLxy2Rpm&jiY%>;Dv!d^mBr=7?fx&zU1#@v4wtRk ziX84&eD_Pf`^i9=@3&UlNcE1T+Kzu}xI#^u@LogX^?llE=l5HXwV%K>1$!Zz)%I5X znSA5TX2ApZ;oJ!QK#z(bQ1ov-BwF`_V5ZjtqwOTwpg>^h4b$g(QtAMKqf4E-zBCL1 zPnSl9NW3`+f|K4H8U>PUodBVc-byeej=Uh_9(Z9k$QtAf@&=s-8wv3<=MC2s*_KKX z1OiGEc`2Xa5my)7!LzO_Fp6KhVopWS>mD6n*A!m2Wcd!vp2M&34fk2Nh_~F$y=l_Z hZ;DDT2dbI?U>BX-MScHTMkyHFc83m;9w^PE{Xg<%{j~r9 delta 620 zcmYk3O=uHA6vyXnW|M4^-Plc9)0F0``Pd{Sm_rhwr9r6*oi-GL_|bz_tOsk=ZV)L7 zDSFV83Ul)ddTI|M)OZ$pX$rlx^dJP|QLjmA4_?GKTLcH*Z~pH;A8(k~&b~6VLsfMV z9LnPT+q3$nR+M0zo6-lj8_lN}hu`Ez+V+g{PmVCHj^t#%<{X1KZ#zdI!9f{}CJP{L zAY?9lJQH$J`rqU4?8E%BVt8Z!+-fREs|J6m3}>av7bm$ORW>Zvkx;qjB$YoHKQT5j z0wvomNT(ZZWl`d9J%cA@Glr$ih(JgnEs*EmJ#lDpP_Mv=#+=#*{Gs*{ZZwkK_fjS` zy1ufuvX`GaNU^Tlp}RUB;`M#iGW%L)qi~?*J1Uyb?H!#@>&x}JBrC3-Mgrv?l~t`b z1tc*IU8<;BH%OE`LZ5}M-=(;I*Ir=xCjmAJuYm>V8=)G&hUn)ks;w}v5Z#JQ#xU8I zfJN!H?Tkp831D&BOp5)@31CUuESFI46rs!vx>GtE#B8?@ScdNE4xxuYFk~@mF>Wzw z(Xg07@<+Z^{X9OaCLtmbvtRtsX|DQHu*wVmWo+}hKc~0o-T9>jb3m-l9B=vIpSNEJ zdEjW0&-Al%mxLP-5LdLE<4gB$KDe_mVP3^lbiNiubZh|7CSz@K>X-d7Kyl9(KO#a{ GXa54YH?KrLMc+5rGd`dwKPxr4q*y;YDJ4liF+DY} XBtESuF*mh5zbHFCKRHu>qJ07Y2)`HZ delta 24 ecmX@ZIG>UGGcPX}0}ya#7fj?fX0)4_lK=on$_3v5 diff --git a/agent_framework_oci/templates/agent_template_backend/app/observability/__pycache__/telemetry_observer.cpython-313.pyc b/agent_framework_oci/templates/agent_template_backend/app/observability/__pycache__/telemetry_observer.cpython-313.pyc index 9495cf23358c2ac930be348c1e891b909ded9afc..642f8b719cc5034efeac48648d7ccb2112a498b9 100644 GIT binary patch delta 72 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 literal 0 HcmV?d00001 diff --git a/agent_framework_oci/templates/agent_template_backend/docs/MCP_MULTI_ITEM.md b/agent_framework_oci/templates/agent_template_backend/docs/MCP_MULTI_ITEM.md new file mode 100644 index 00000000..6d5244f3 --- /dev/null +++ b/agent_framework_oci/templates/agent_template_backend/docs/MCP_MULTI_ITEM.md @@ -0,0 +1,363 @@ +# MCP Multi-item — Guia do Desenvolvedor + +## Objetivo + +Use este guia quando uma única intenção do usuário precisa operar sobre **mais de um item do mesmo tipo** em uma chamada MCP, por exemplo: + +- cancelar vários VAS/produtos; +- devolver ou consultar vários pedidos; +- alterar vários ativos; +- processar uma lista de faturas, linhas, contratos ou recursos. + +O framework já possui contratos genéricos para **coleta de listas**, **pré-validação/canonicalização**, **confirmação transacional**, **execução MCP** e **normalização do resultado por item**. O desenvolvedor não deve criar um segundo motor de multi-item dentro do agente. + +## Regra principal + +**Não faça loop de negócio no agente.** O agente declara a tool e seus parâmetros; o runtime mantém estado, confirmação e evidência. A operação em lote deve ser exposta como uma tool MCP que aceite uma coleção, ou como uma tool transacional apoiada por um workflow/MCP que processe a coleção. + +Fluxo recomendado: + +```text +Usuário cita N itens + -> Router/Agent seleciona a tool + -> Runtime coleta/reconcilia parâmetro array/list + -> (opcional) pre-validation canonicaliza itens + -> Runtime pede UMA confirmação coerente para o conjunto + -> MCP recebe a coleção + -> MCP/workflow processa item a item + -> MCP devolve results[] com success/ok por item + -> Framework normaliza SUCCESS / PARTIAL_SUCCESS / FAILED + -> Composição final relata sucessos e falhas individualmente +``` + +## 1. Declarar um parâmetro de lista em `tools.yaml` + +O reconciliador transacional do framework aceita `type: array` ou `type: list`. + +```yaml +tools: + cancelar_produtos: + description: Cancela um ou mais produtos do cliente. + mcp_server: contas + enabled: true + tool_type: action + confirmation_required: true + requires: [items] + args_schema: + items: + type: array + label: os produtos + description: Lista de produtos que o cliente deseja cancelar. + user_prompt: Informe quais produtos deseja cancelar. +``` + +O runtime pode reconciliar uma frase como: + +```text +quero cancelar TIM Fashion, Aya Audiobooks e Neymar Jr +``` + +para um argumento lógico semelhante a: + +```json +{ + "items": ["TIM Fashion", "Aya Audiobooks", "Neymar Jr"] +} +``` + +A semântica de domínio e a validação dos nomes continuam pertencendo ao MCP/pre-validator, não ao core. + +## 2. Quando usar pre-validation + +Use `tool_policies.yaml` quando a lista precisa ser resolvida/canonicalizada antes da confirmação. + +```yaml +tool_policies: + cancelar_produtos: + operation_type: transactional + require_confirmation: true + requires: [items] + pre_validation: + enabled: true + tool: validar_produtos_cancelamento + fail_open: false +``` + +O pre-validator pode retornar `eligible: true` e substituir argumentos por valores canônicos em `transaction_decision.resolved_arguments`: + +```json +{ + "eligible": true, + "transaction_decision": { + "resolved_arguments": { + "items": [ + {"name": "TIM Fashion Mensal", "id": "1001"}, + {"name": "Aya Audiobooks Premium", "id": "1002"}, + {"name": "Neymar Jr", "id": "1003"} + ] + }, + "target_tool": "cancelar_produtos", + "confirmation_message": "Você confirma o cancelamento de TIM Fashion Mensal, Aya Audiobooks Premium e Neymar Jr?" + } +} +``` + +### Importante para validação parcial + +O contrato `eligible` da pre-validation é global. Portanto, **não retorne `eligible: false` apenas porque um item da lista falhou**, caso os demais ainda possam ser processados. Isso encerraria toda a transação. + +Para permitir resultado parcial, a estratégia recomendada é: + +1. retornar `eligible: true` quando existe pelo menos um item acionável; +2. preservar/canonicalizar a coleção em `resolved_arguments`; +3. deixar a tool primária devolver o resultado terminal de **cada item** em `results[]`. + +Se nenhum item puder ser processado, então `eligible: false` é apropriado. + +## 3. Contrato de entrada do MCP + +Prefira uma única chamada MCP com uma coleção explícita: + +```json +{ + "tool_name": "cancelar_produtos", + "arguments": { + "customer_id": "123", + "items": [ + {"name": "TIM Fashion Mensal", "id": "1001"}, + {"name": "Aya Audiobooks Premium", "id": "1002"}, + {"name": "Neymar Jr", "id": "1003"} + ] + } +} +``` + +O framework **não deve ser usado como um loop improvisado que chama N vezes uma tool escalar a partir do agente**. Se o backend só possui API unitária, o fan-out pode ficar encapsulado no MCP Server ou em um workflow de domínio, mantendo uma única tool lógica para o agente. + +## 4. Contrato obrigatório de resultado por item + +Para o framework reconhecer multi-item automaticamente, a **tool primária solicitada** deve expor uma lista `results` com **dois ou mais itens**, e cada item deve possuir um booleano `success` ou `ok`. + +Exemplo: + +```json +{ + "ok": true, + "result": { + "results": [ + {"id": "1001", "subject": "TIM Fashion Mensal", "success": true}, + {"id": "1002", "subject": "Aya Audiobooks Premium", "success": false, "reason": "not_found"}, + {"id": "1003", "subject": "Neymar Jr", "success": true} + ] + } +} +``` + +Campos como `id`, `subject`, `name`, `reason`, `error`, `protocol` e outros são de domínio e opcionais. O sinal estrutural exigido pelo normalizador é `success: true|false` ou `ok: true|false` por item. + +### Workflow-backed tool + +Se a tool é executada por workflow, o caminho preferencial e autoritativo é: + +```text +workflow.output[tool_name].results +``` + +Exemplo: + +```json +{ + "ok": false, + "result": { + "status": "COMPLETED", + "output": { + "cancelar_produtos": { + "results": [ + {"subject": "A", "success": true}, + {"subject": "B", "success": false, "reason": "not_found"}, + {"subject": "C", "success": true} + ] + }, + "etapa_auxiliar": { + "success": false, + "error": "falha em pós-processamento" + } + } + }, + "error": "falha em pós-processamento" +} +``` + +O runtime preserva o resultado da operação primária e não permite que uma falha auxiliar apague itens já concluídos. + +## 5. O que o framework produz automaticamente + +Com `results[]` válido, o runtime adiciona: + +```json +{ + "multi_item_status": "PARTIAL_SUCCESS", + "partial_success": true, + "metadata": { + "multi_item": { + "status": "PARTIAL_SUCCESS", + "items_count": 3, + "items_succeeded_count": 2, + "items_failed_count": 1, + "primary_tool": "cancelar_produtos" + } + } +} +``` + +Estados possíveis: + +| Situação | `multi_item_status` | +|---|---| +| todos os itens concluíram | `SUCCESS` | +| parte concluiu e parte falhou | `PARTIAL_SUCCESS` | +| todos falharam | `FAILED` | + +Se uma etapa posterior fizer o wrapper retornar `ok=false`, mas pelo menos um item primário tiver sucesso, o framework preserva para auditoria: + +```json +{ + "ok": true, + "original_ok": false, + "secondary_error": "erro da etapa posterior" +} +``` + +Isso evita transformar sucesso parcial/real em falha total na resposta ao usuário. + +## 6. O que NÃO fazer + +Evite estes padrões: + +```python +# NÃO: motor multi-item paralelo dentro do agente +for product in products: + await tool_router.call("cancelar_produto", {"product": product}) +``` + +```json +// NÃO: apenas um approved global sem evidência por item +{ + "approved": false, + "error": "um item falhou" +} +``` + +```json +// NÃO: um único success agregado quando houve resultados mistos +{ + "success": false, + "message": "operação bloqueada" +} +``` + +Esses formatos perdem a evidência terminal individual e podem fazer itens concluídos desaparecerem da composição final. + +## 7. Exemplo completo: vários pedidos + +### `tools.yaml` + +```yaml +tools: + cancelar_pedidos: + description: Cancela um ou mais pedidos. + mcp_server: retail + enabled: true + tool_type: action + confirmation_required: true + requires: [order_ids] + args_schema: + order_ids: + type: array + label: os pedidos + description: Lista de identificadores de pedidos a cancelar. + user_prompt: Quais pedidos deseja cancelar? +``` + +### Retorno MCP + +```json +{ + "ok": true, + "result": { + "results": [ + {"order_id": "P-100", "success": true, "protocol": "ABC1"}, + {"order_id": "P-101", "success": false, "reason": "already_shipped"}, + {"order_id": "P-102", "success": true, "protocol": "ABC3"} + ] + } +} +``` + +O framework classificará automaticamente como `PARTIAL_SUCCESS` e fornecerá ao LLM a instrução de relatar os resultados item a item. + +## 8. Read-only multi-item + +A mesma estrutura serve para consultas em lote. A diferença é que normalmente não existe confirmação: + +```yaml +tool_policies: + consultar_pedidos: + operation_type: read_only + require_confirmation: false +``` + +A tool ainda pode retornar `results[]` com `success/ok` por item para que uma consulta parcialmente indisponível não esconda as consultas bem-sucedidas. + +## 9. Idempotência e protocolos + +Em operações com efeito colateral: + +- use uma chave de idempotência de requisição e, quando necessário, uma chave por item; +- devolva protocolo/operation id no próprio item; +- não dependa apenas de uma mensagem textual agregada; +- em retry, preserve os itens já concluídos e execute apenas o que a regra de domínio permitir. + +O framework preserva evidência; a política de idempotência do sistema de destino continua pertencendo ao MCP/workflow de domínio. + +## 10. Checklist para o desenvolvedor + +- [ ] A tool aceita `array/list` quando o caso de uso é multi-item. +- [ ] Não existe loop MCP de negócio dentro da classe do agente. +- [ ] Se houver canonicalização, ela está em pre-validation/MCP, não hardcoded no agente. +- [ ] A confirmação mostra o conjunto efetivo de itens. +- [ ] A tool primária retorna `results[]` com `success` ou `ok` por item. +- [ ] Resultado parcial não é reduzido a um único `approved=false` ou `success=false` global. +- [ ] Workflow usa `output[tool_name].results` para a evidência terminal da tool primária. +- [ ] Testes cobrem todos-sucesso, parcial, todos-falha e falha auxiliar posterior. +- [ ] A resposta final menciona sucessos e falhas quando houver `PARTIAL_SUCCESS`. + +## 11. Onde o comportamento existe no framework + +Referências atuais: + +```text +libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py + - coerção de type=array/list + +libs/agent_framework/src/agent_framework/runtime/agent_runtime.py + - pre-validation e resolved_arguments + - _primary_multi_item_outcomes() + - _normalize_multi_item_tool_result() + - instrução de composição multi-item para o LLM + +tests/test_multi_item_result_normalization.py + - regressões de SUCCESS/PARTIAL_SUCCESS e proteção contra falha auxiliar +``` + +## 12. Resumo de responsabilidade + +| Camada | Responsabilidade | +|---|---| +| Agente | declarar intenção/tool e usar o runtime; não implementar motor multi-item | +| `tools.yaml` | declarar parâmetro `array/list` e schema | +| `tool_policies.yaml` | confirmação e pre-validation | +| Pre-validator MCP | resolver/canonicalizar entidades e argumentos | +| Tool MCP/workflow | executar a coleção e produzir resultado por item | +| Framework runtime | manter estado, confirmação, normalizar resultado multi-item e preservar evidência | +| LLM/presentation | transformar evidências em resposta, sem apagar sucesso/falha individual | diff --git a/agent_framework_oci/templates/agent_template_backend_day_zero/README_DAY_ZERO.md b/agent_framework_oci/templates/agent_template_backend_day_zero/README_DAY_ZERO.md index 869ed33c..2e9f3349 100644 --- a/agent_framework_oci/templates/agent_template_backend_day_zero/README_DAY_ZERO.md +++ b/agent_framework_oci/templates/agent_template_backend_day_zero/README_DAY_ZERO.md @@ -87,3 +87,8 @@ Esses arquivos são o esqueleto de execução usando o framework. # Política opcional de tools O arquivo `config/tool_policies.yaml` classifica tools como `read_only` ou `transactional`. Para uma transação real, ative `require_confirmation: true`; chamadas sem `confirmed: true` ou `confirmation: true` serão bloqueadas antes do MCP. A ausência do arquivo preserva o comportamento de templates anteriores. + + +## MCP multi-item + +Para listas de produtos/pedidos/itens, não crie loop MCP no agente. O runtime aceita parâmetros `array/list` e normaliza `results[]` por item em `SUCCESS`, `PARTIAL_SUCCESS` ou `FAILED`. Consulte [`docs/MCP_MULTI_ITEM.md`](docs/MCP_MULTI_ITEM.md) antes de criar qualquer mecanismo próprio de lote. diff --git a/agent_framework_oci/templates/agent_template_backend_day_zero/docs/MCP_MULTI_ITEM.md b/agent_framework_oci/templates/agent_template_backend_day_zero/docs/MCP_MULTI_ITEM.md new file mode 100644 index 00000000..6d5244f3 --- /dev/null +++ b/agent_framework_oci/templates/agent_template_backend_day_zero/docs/MCP_MULTI_ITEM.md @@ -0,0 +1,363 @@ +# MCP Multi-item — Guia do Desenvolvedor + +## Objetivo + +Use este guia quando uma única intenção do usuário precisa operar sobre **mais de um item do mesmo tipo** em uma chamada MCP, por exemplo: + +- cancelar vários VAS/produtos; +- devolver ou consultar vários pedidos; +- alterar vários ativos; +- processar uma lista de faturas, linhas, contratos ou recursos. + +O framework já possui contratos genéricos para **coleta de listas**, **pré-validação/canonicalização**, **confirmação transacional**, **execução MCP** e **normalização do resultado por item**. O desenvolvedor não deve criar um segundo motor de multi-item dentro do agente. + +## Regra principal + +**Não faça loop de negócio no agente.** O agente declara a tool e seus parâmetros; o runtime mantém estado, confirmação e evidência. A operação em lote deve ser exposta como uma tool MCP que aceite uma coleção, ou como uma tool transacional apoiada por um workflow/MCP que processe a coleção. + +Fluxo recomendado: + +```text +Usuário cita N itens + -> Router/Agent seleciona a tool + -> Runtime coleta/reconcilia parâmetro array/list + -> (opcional) pre-validation canonicaliza itens + -> Runtime pede UMA confirmação coerente para o conjunto + -> MCP recebe a coleção + -> MCP/workflow processa item a item + -> MCP devolve results[] com success/ok por item + -> Framework normaliza SUCCESS / PARTIAL_SUCCESS / FAILED + -> Composição final relata sucessos e falhas individualmente +``` + +## 1. Declarar um parâmetro de lista em `tools.yaml` + +O reconciliador transacional do framework aceita `type: array` ou `type: list`. + +```yaml +tools: + cancelar_produtos: + description: Cancela um ou mais produtos do cliente. + mcp_server: contas + enabled: true + tool_type: action + confirmation_required: true + requires: [items] + args_schema: + items: + type: array + label: os produtos + description: Lista de produtos que o cliente deseja cancelar. + user_prompt: Informe quais produtos deseja cancelar. +``` + +O runtime pode reconciliar uma frase como: + +```text +quero cancelar TIM Fashion, Aya Audiobooks e Neymar Jr +``` + +para um argumento lógico semelhante a: + +```json +{ + "items": ["TIM Fashion", "Aya Audiobooks", "Neymar Jr"] +} +``` + +A semântica de domínio e a validação dos nomes continuam pertencendo ao MCP/pre-validator, não ao core. + +## 2. Quando usar pre-validation + +Use `tool_policies.yaml` quando a lista precisa ser resolvida/canonicalizada antes da confirmação. + +```yaml +tool_policies: + cancelar_produtos: + operation_type: transactional + require_confirmation: true + requires: [items] + pre_validation: + enabled: true + tool: validar_produtos_cancelamento + fail_open: false +``` + +O pre-validator pode retornar `eligible: true` e substituir argumentos por valores canônicos em `transaction_decision.resolved_arguments`: + +```json +{ + "eligible": true, + "transaction_decision": { + "resolved_arguments": { + "items": [ + {"name": "TIM Fashion Mensal", "id": "1001"}, + {"name": "Aya Audiobooks Premium", "id": "1002"}, + {"name": "Neymar Jr", "id": "1003"} + ] + }, + "target_tool": "cancelar_produtos", + "confirmation_message": "Você confirma o cancelamento de TIM Fashion Mensal, Aya Audiobooks Premium e Neymar Jr?" + } +} +``` + +### Importante para validação parcial + +O contrato `eligible` da pre-validation é global. Portanto, **não retorne `eligible: false` apenas porque um item da lista falhou**, caso os demais ainda possam ser processados. Isso encerraria toda a transação. + +Para permitir resultado parcial, a estratégia recomendada é: + +1. retornar `eligible: true` quando existe pelo menos um item acionável; +2. preservar/canonicalizar a coleção em `resolved_arguments`; +3. deixar a tool primária devolver o resultado terminal de **cada item** em `results[]`. + +Se nenhum item puder ser processado, então `eligible: false` é apropriado. + +## 3. Contrato de entrada do MCP + +Prefira uma única chamada MCP com uma coleção explícita: + +```json +{ + "tool_name": "cancelar_produtos", + "arguments": { + "customer_id": "123", + "items": [ + {"name": "TIM Fashion Mensal", "id": "1001"}, + {"name": "Aya Audiobooks Premium", "id": "1002"}, + {"name": "Neymar Jr", "id": "1003"} + ] + } +} +``` + +O framework **não deve ser usado como um loop improvisado que chama N vezes uma tool escalar a partir do agente**. Se o backend só possui API unitária, o fan-out pode ficar encapsulado no MCP Server ou em um workflow de domínio, mantendo uma única tool lógica para o agente. + +## 4. Contrato obrigatório de resultado por item + +Para o framework reconhecer multi-item automaticamente, a **tool primária solicitada** deve expor uma lista `results` com **dois ou mais itens**, e cada item deve possuir um booleano `success` ou `ok`. + +Exemplo: + +```json +{ + "ok": true, + "result": { + "results": [ + {"id": "1001", "subject": "TIM Fashion Mensal", "success": true}, + {"id": "1002", "subject": "Aya Audiobooks Premium", "success": false, "reason": "not_found"}, + {"id": "1003", "subject": "Neymar Jr", "success": true} + ] + } +} +``` + +Campos como `id`, `subject`, `name`, `reason`, `error`, `protocol` e outros são de domínio e opcionais. O sinal estrutural exigido pelo normalizador é `success: true|false` ou `ok: true|false` por item. + +### Workflow-backed tool + +Se a tool é executada por workflow, o caminho preferencial e autoritativo é: + +```text +workflow.output[tool_name].results +``` + +Exemplo: + +```json +{ + "ok": false, + "result": { + "status": "COMPLETED", + "output": { + "cancelar_produtos": { + "results": [ + {"subject": "A", "success": true}, + {"subject": "B", "success": false, "reason": "not_found"}, + {"subject": "C", "success": true} + ] + }, + "etapa_auxiliar": { + "success": false, + "error": "falha em pós-processamento" + } + } + }, + "error": "falha em pós-processamento" +} +``` + +O runtime preserva o resultado da operação primária e não permite que uma falha auxiliar apague itens já concluídos. + +## 5. O que o framework produz automaticamente + +Com `results[]` válido, o runtime adiciona: + +```json +{ + "multi_item_status": "PARTIAL_SUCCESS", + "partial_success": true, + "metadata": { + "multi_item": { + "status": "PARTIAL_SUCCESS", + "items_count": 3, + "items_succeeded_count": 2, + "items_failed_count": 1, + "primary_tool": "cancelar_produtos" + } + } +} +``` + +Estados possíveis: + +| Situação | `multi_item_status` | +|---|---| +| todos os itens concluíram | `SUCCESS` | +| parte concluiu e parte falhou | `PARTIAL_SUCCESS` | +| todos falharam | `FAILED` | + +Se uma etapa posterior fizer o wrapper retornar `ok=false`, mas pelo menos um item primário tiver sucesso, o framework preserva para auditoria: + +```json +{ + "ok": true, + "original_ok": false, + "secondary_error": "erro da etapa posterior" +} +``` + +Isso evita transformar sucesso parcial/real em falha total na resposta ao usuário. + +## 6. O que NÃO fazer + +Evite estes padrões: + +```python +# NÃO: motor multi-item paralelo dentro do agente +for product in products: + await tool_router.call("cancelar_produto", {"product": product}) +``` + +```json +// NÃO: apenas um approved global sem evidência por item +{ + "approved": false, + "error": "um item falhou" +} +``` + +```json +// NÃO: um único success agregado quando houve resultados mistos +{ + "success": false, + "message": "operação bloqueada" +} +``` + +Esses formatos perdem a evidência terminal individual e podem fazer itens concluídos desaparecerem da composição final. + +## 7. Exemplo completo: vários pedidos + +### `tools.yaml` + +```yaml +tools: + cancelar_pedidos: + description: Cancela um ou mais pedidos. + mcp_server: retail + enabled: true + tool_type: action + confirmation_required: true + requires: [order_ids] + args_schema: + order_ids: + type: array + label: os pedidos + description: Lista de identificadores de pedidos a cancelar. + user_prompt: Quais pedidos deseja cancelar? +``` + +### Retorno MCP + +```json +{ + "ok": true, + "result": { + "results": [ + {"order_id": "P-100", "success": true, "protocol": "ABC1"}, + {"order_id": "P-101", "success": false, "reason": "already_shipped"}, + {"order_id": "P-102", "success": true, "protocol": "ABC3"} + ] + } +} +``` + +O framework classificará automaticamente como `PARTIAL_SUCCESS` e fornecerá ao LLM a instrução de relatar os resultados item a item. + +## 8. Read-only multi-item + +A mesma estrutura serve para consultas em lote. A diferença é que normalmente não existe confirmação: + +```yaml +tool_policies: + consultar_pedidos: + operation_type: read_only + require_confirmation: false +``` + +A tool ainda pode retornar `results[]` com `success/ok` por item para que uma consulta parcialmente indisponível não esconda as consultas bem-sucedidas. + +## 9. Idempotência e protocolos + +Em operações com efeito colateral: + +- use uma chave de idempotência de requisição e, quando necessário, uma chave por item; +- devolva protocolo/operation id no próprio item; +- não dependa apenas de uma mensagem textual agregada; +- em retry, preserve os itens já concluídos e execute apenas o que a regra de domínio permitir. + +O framework preserva evidência; a política de idempotência do sistema de destino continua pertencendo ao MCP/workflow de domínio. + +## 10. Checklist para o desenvolvedor + +- [ ] A tool aceita `array/list` quando o caso de uso é multi-item. +- [ ] Não existe loop MCP de negócio dentro da classe do agente. +- [ ] Se houver canonicalização, ela está em pre-validation/MCP, não hardcoded no agente. +- [ ] A confirmação mostra o conjunto efetivo de itens. +- [ ] A tool primária retorna `results[]` com `success` ou `ok` por item. +- [ ] Resultado parcial não é reduzido a um único `approved=false` ou `success=false` global. +- [ ] Workflow usa `output[tool_name].results` para a evidência terminal da tool primária. +- [ ] Testes cobrem todos-sucesso, parcial, todos-falha e falha auxiliar posterior. +- [ ] A resposta final menciona sucessos e falhas quando houver `PARTIAL_SUCCESS`. + +## 11. Onde o comportamento existe no framework + +Referências atuais: + +```text +libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py + - coerção de type=array/list + +libs/agent_framework/src/agent_framework/runtime/agent_runtime.py + - pre-validation e resolved_arguments + - _primary_multi_item_outcomes() + - _normalize_multi_item_tool_result() + - instrução de composição multi-item para o LLM + +tests/test_multi_item_result_normalization.py + - regressões de SUCCESS/PARTIAL_SUCCESS e proteção contra falha auxiliar +``` + +## 12. Resumo de responsabilidade + +| Camada | Responsabilidade | +|---|---| +| Agente | declarar intenção/tool e usar o runtime; não implementar motor multi-item | +| `tools.yaml` | declarar parâmetro `array/list` e schema | +| `tool_policies.yaml` | confirmação e pre-validation | +| Pre-validator MCP | resolver/canonicalizar entidades e argumentos | +| Tool MCP/workflow | executar a coleção e produzir resultado por item | +| Framework runtime | manter estado, confirmação, normalizar resultado multi-item e preservar evidência | +| LLM/presentation | transformar evidências em resposta, sem apagar sucesso/falha individual | diff --git a/agent_framework_oci/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc b/agent_framework_oci/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc index 4af29071b0aac0e7bdd0affc4e1446fa20f6a08e..4aee37c9f51d0cf9b457b5a7f0a4974d90d5117e 100644 GIT binary patch delta 41 vcmZ3;Hj$0{GcPX}0}$NSTDy_kl}W%KR2&LKP9mwQ9m&~HLoN-IX|x?u{b^{u{bp+ LGcR>=0@FqS^QaR| diff --git a/agent_framework_oci/tests/__pycache__/test_advanced_developer_documentation.cpython-313-pytest-9.0.2.pyc b/agent_framework_oci/tests/__pycache__/test_advanced_developer_documentation.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7ed2d540c9731c45a993b66b4232de9b15e50fe GIT binary patch literal 26081 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 literal 0 HcmV?d00001 diff --git a/agent_framework_oci/tests/__pycache__/test_multi_item_documentation.cpython-313-pytest-9.0.2.pyc b/agent_framework_oci/tests/__pycache__/test_multi_item_documentation.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4de9c84118a4b21e2b7c9f65f4415d3ea690164 GIT binary patch literal 8387 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 KE5<%Y-u+*ry-TqG literal 0 HcmV?d00001 diff --git a/agent_framework_oci/tests/__pycache__/test_readme_financeiro_agent_example.cpython-313-pytest-9.0.2.pyc b/agent_framework_oci/tests/__pycache__/test_readme_financeiro_agent_example.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..789ed502124924d63c4ae7049257383ffcb9c2c0 GIT binary patch literal 20483 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