diff --git a/.env.example b/.env.example index d90a4b2..6a867c8 100644 --- a/.env.example +++ b/.env.example @@ -212,3 +212,25 @@ LONG_TERM_MEMORY_INJECT_CONTEXT=true # Keep disabled in the generic framework; agents may enable their own YAML mapping. OBSERVABILITY_CODE_MAPPING_ENABLED=false OBSERVABILITY_CODE_MAPPING_PATH= + +############################################################################### +# RAG provider selection (mutually exclusive at runtime) +############################################################################### +# standard = RAG original do agent_framework_oci (default, backward compatible) +# kbdb = KBDB enterprise via PKG_KB_SERVING.SEARCH_KNOWLEDGE_BASE +RAG_PROVIDER=standard + +# Somente usados quando RAG_PROVIDER=kbdb. Se vazios, credenciais caem para ADB_*. +KBDB_DB_USER= +KBDB_DB_PASSWORD= +KBDB_DB_DSN= +KBDB_DB_WALLET_LOCATION= +KBDB_DB_WALLET_PASSWORD= +KBDB_SEARCH_TYPE=hybrid +KBDB_NODE_EXPANSION=true +KBDB_NODE_MAX_RELATED=8 +KBDB_GRAPH_CROSS_REF=false +KBDB_MAX_CROSS_REF_HOPS=1 +KBDB_DOCUMENT_TYPE=customer_safe +KBDB_METADATA_JSON= +KBDB_MIN_SCORE= diff --git a/README.md b/README.md index ba4946e..1e74b65 100644 --- a/README.md +++ b/README.md @@ -11176,3 +11176,7 @@ A adoção das funcionalidades do `Tuning-Performance` pode proporcionar: * comportamento consistente entre diferentes agentes e projetos. O conteúdo desta pasta deve ser tratado como uma extensão adicional do framework. Sua utilização requer implementação, configuração, testes funcionais e validação das regras de negócio antes da implantação em produção. + +### RAG provider alternativo (KBDB Enterprise) + +O RAG original continua sendo o default (`RAG_PROVIDER=standard`). Para usar a arquitetura KBDB enterprise como alternativa de serving, configure `RAG_PROVIDER=kbdb`. Os agentes continuam usando o mesmo `RagService`/`_retrieve_rag_context()` e os dois backends não são executados simultaneamente. Consulte `docs/RAG_PROVIDER_KBDB.md`. diff --git a/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/data/agent_framework.db b/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/data/agent_framework.db deleted file mode 100644 index ddf1883..0000000 Binary files a/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/data/agent_framework.db and /dev/null differ diff --git a/Tuning-Performance/Transaction_Evidence/agent_template_backend/.env b/Tuning-Performance/Transaction_Evidence/agent_template_backend/.env.example similarity index 81% rename from Tuning-Performance/Transaction_Evidence/agent_template_backend/.env rename to Tuning-Performance/Transaction_Evidence/agent_template_backend/.env.example index 4556734..a8a666c 100644 --- a/Tuning-Performance/Transaction_Evidence/agent_template_backend/.env +++ b/Tuning-Performance/Transaction_Evidence/agent_template_backend/.env.example @@ -14,45 +14,38 @@ CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 # LLM - OCI Generative AI como provider principal ############################################################################### # Opções: mock, oci_openai, oci_sdk, openai_compatible -LLM_PROVIDER=oci_sdk +LLM_PROVIDER=oci_openai LLM_TEMPERATURE=0.2 LLM_MAX_TOKENS=2048 LLM_TIMEOUT_SECONDS=120 # OCI OpenAI-compatible endpoint -OCI_GENAI_BASE_URL=https://inference.generativeai.us-chicago-1.oci.oraclecloud.com +OCI_GENAI_BASE_URL=https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/openai/v1 OCI_GENAI_MODEL=openai.gpt-4.1 -OCI_GENAI_API_KEY=sk-ph3FgX6iP3fxAQCXb9IpPIDTadkeeYAWntUWhzcWysIM6zsS +OCI_GENAI_API_KEY=sk-ph3FgX6ph3FgX6ph3FgX6ph3FgX6ph3FgX6ph3FgX6 OCI_GENAI_PROJECT_OCID= -#OCI_GENAI_BASE_URL=https://pegruagntaiatenddev.pe.inference.generativeai.sa-saopaulo-1.oci.oraclecloud.com -#OCI_GENAI_MODEL=openai.gpt-4.1 -#OCI_GENAI_API_KEY= -#OCI_GENAI_PROJECT_OCID= - - -# OCI_AUTH_MODE=config_file|instance_principal|resource_principal -OCI_AUTH_MODE=config_file # OCI SDK / signer / profiles OCI_CONFIG_FILE=~/.oci/config -OCI_PROFILE=LATINOAMERICA-Chicago -OCI_COMPARTMENT_ID=ocid1.compartment.oc1..aaaaaaaaexpiw4a7dio64mkfv2t273s2hgdl6mgfvvyv7tycalnjlvpvfl3q +OCI_PROFILE=DEFAULT +OCI_COMPARTMENT_ID=ocid1.compartment.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa OCI_REGION=us-chicago-1 ############################################################################### # Persistência ############################################################################### # Opções: memory, autonomous, mongodb -SESSION_REPOSITORY_PROVIDER=autonomous -MEMORY_REPOSITORY_PROVIDER=autonomous -CHECKPOINT_REPOSITORY_PROVIDER=autonomous +SESSION_REPOSITORY_PROVIDER=sqlite +MEMORY_REPOSITORY_PROVIDER=sqlite +CHECKPOINT_REPOSITORY_PROVIDER=sqlite +SQLITE_DB_PATH=./data/agent_framework.db # Autonomous Database ADB_USER=admin -ADB_PASSWORD=Moniquinha19721972 -ADB_DSN=oradb23ai_high -ADB_WALLET_LOCATION=/mnt/d/Dropbox/ORACLE/LatinoAmerica/Wallet_ORADB23ai -ADB_WALLET_PASSWORD=Moniquinha1972 +ADB_PASSWORD=fjhsdf04954hf +ADB_DSN=oradb23aidev_high +ADB_WALLET_LOCATION=/ORACLE/DEFAULT/Wallet_ORADB23aiDev +ADB_WALLET_PASSWORD=fjhsdf04954hf ADB_TABLE_PREFIX=AGENTFW # MongoDB - também pode representar Autonomous usando API compatível com Mongo, se habilitada no ambiente @@ -66,10 +59,10 @@ ENABLE_REDIS_CACHE=false ############################################################################### # RAG / Vector / Graph ############################################################################### -VECTOR_STORE_PROVIDER=autonomous -GRAPH_STORE_PROVIDER=autonomous +VECTOR_STORE_PROVIDER=sqlite +GRAPH_STORE_PROVIDER=sqlite RAG_TOP_K=5 -EMBEDDING_PROVIDER=oci +EMBEDDING_PROVIDER=mock OCI_EMBEDDING_MODEL=cohere.embed-multilingual-v3.0 RAG_FILE_GLOBS=*.md,*.txt,*.yaml,*.yml,*.json @@ -77,21 +70,14 @@ RAG_FILE_GLOBS=*.md,*.txt,*.yaml,*.yml,*.json # Observabilidade ############################################################################### ENABLE_LANGFUSE=true - # Opcional: verbose, compact -LANGFUSE_TRACE_MODE=compact -# Nome customizado do trace pai, ex.: backoffice.checklist.workflow ou backoffice.emulador.workflow -LANGFUSE_COMPACT_VISIBLE_EVENT_PREFIXES=AGA.,NOC., IC. -LANGFUSE_COMPACT_SUPPRESSED_PREFIXES=llm.chat_completion -LANGFUSE_IGNORE_HEALTHCHECKS=true -LANGFUSE_IGNORED_PATHS=/health,/ready,/metrics -LANGFUSE_PUBLIC_KEY=pk-lf-4a1e3921-5158-4fd3-a16d-7a77549fb312 -LANGFUSE_SECRET_KEY=sk-lf-efc6fd59-c5ec-4858-b6ec-4aa129734915 +LANGFUSE_TRACE_MODE=compact # Opcional: verbose, compact +LANGFUSE_PUBLIC_KEY=pk-lf-2f9da109-5b0f-4c78-b61d-9598ed787eba +LANGFUSE_SECRET_KEY=sk-lf-a4cb0cdd-f2ea-4468-9911-cebeb91ba944 LANGFUSE_HOST=http://localhost:3005 ENABLE_OTEL=false OTEL_EXPORTER_OTLP_ENDPOINT= OTEL_SERVICE_NAME=ai-agent-template ENABLE_LANGFUSE_OPENAI_AUTO_INSTRUMENTATION=true -ENABLE_LANGFUSE_ANALYTICS_PUBLISHER=false ############################################################################### # Analytics / Observer corporativo @@ -99,7 +85,7 @@ ENABLE_LANGFUSE_ANALYTICS_PUBLISHER=false # Quando true, AgentObserver publica eventos IC.*, NOC.* e GRL.* nos providers abaixo. ENABLE_ANALYTICS=false # Providers aceitos: oci_streaming,pubsub,noop -ANALYTICS_PROVIDERS=oci_streaming +ANALYTICS_PROVIDERS=pubsub # Compatibilidade FIRST/TIM: pode informar AGENT_PUBSUB_TOPIC diretamente. AGENT_PUBSUB_TOPIC= GCP_PUBSUB_TOPIC_PATH= @@ -162,6 +148,7 @@ ROUTE_STICKINESS_HISTORY_TURNS=2 ROUTE_STICKINESS_MAX_TOKENS=80 HUMAN_HANDOFF_MESSAGE=Vou encaminhar seu atendimento para uma pessoa. END_SESSION_MESSAGE=Atendimento encerrado. Obrigado pelo contato. +SESSION_ALREADY_ENDED_MESSAGE=Este atendimento já foi encerrado. Inicie uma nova sessão para continuar. ############################################################################### # MCP / Tools @@ -169,13 +156,14 @@ END_SESSION_MESSAGE=Atendimento encerrado. Obrigado pelo contato. ENABLE_MCP_TOOLS=true MCP_SERVERS_CONFIG_PATH=./config/mcp_servers.yaml TOOLS_CONFIG_PATH=./config/tools.yaml +TOOL_POLICIES_PATH=./config/tool_policies.yaml MCP_TOOL_TIMEOUT_SECONDS=30 # router = EnterpriseRouter seleciona um agente; supervisor = pode acionar múltiplos agentes ROUTING_MODE=router # Usage/cost accounting -USAGE_REPOSITORY_PROVIDER=autonomous +USAGE_REPOSITORY_PROVIDER=sqlite IDENTITY_CONFIG_PATH=./config/identity.yaml MCP_PARAMETER_MAPPING_PATH=./config/mcp_parameter_mapping.yaml @@ -192,6 +180,18 @@ MEMORY_SUMMARY_USE_LLM=true MEMORY_INJECT_RECENT_MESSAGES=true MEMORY_INJECT_SUMMARY=true +############################################################################### +# MCP Gateway +############################################################################### +# true = framework routes tool calls to the dedicated MCP Gateway. +# false = framework calls MCP servers directly from mcp_servers.yaml. +MCP_GATEWAY_ENABLED=true +MCP_GATEWAY_URL=http://localhost:8300 +MCP_GATEWAY_TIMEOUT_SECONDS=60 +# MCP_GATEWAY_TOKEN= +MCP_GATEWAY_AGENT_ID=telecom_contas +MCP_GATEWAY_TENANT_ID=default + ############################################################################### # LONG-TERM MEMORY ############################################################################### diff --git a/docs/RAG_PROVIDER_KBDB.md b/docs/RAG_PROVIDER_KBDB.md new file mode 100644 index 0000000..65d60a8 --- /dev/null +++ b/docs/RAG_PROVIDER_KBDB.md @@ -0,0 +1,94 @@ +# RAG alternativo: Standard x KBDB Enterprise + +O framework passa a suportar dois backends de retrieval pelo mesmo contrato `RagService`, sem alterar os agentes nem `_retrieve_rag_context()`. + +## Seleção + +```env +RAG_PROVIDER=standard # default: comportamento anterior +# ou +RAG_PROVIDER=kbdb # KBDB enterprise +``` + +A seleção é exclusiva por processo. Os dois RAGs não executam juntos e não compartilham vector store, graph store ou ingestão. + +## `standard` + +Mantém integralmente o RAG já existente no `agent_framework_oci`: `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, embedding, query rewrite, compression, retrieval guardrails e geração continuam válidos. + +## `kbdb` + +O framework integra somente a porta estável de serving do projeto KBDB: + +`PKG_KB_SERVING.SEARCH_KNOWLEDGE_BASE` + +O pipeline enterprise continua externo ao runtime do agente e preserva sua própria arquitetura RAW → SILVER → GOLD, HVI/hybrid search, property graph, publicação, lifecycle, auditoria e observabilidade. + +O envelope KBDB é adaptado para `RagResult`/`VectorDocument`; portanto os agentes existentes continuam chamando `_retrieve_rag_context()` e os retrieval guardrails do framework continuam depois do retrieval. + +### Configuração + +```env +RAG_PROVIDER=kbdb +RAG_TOP_K=5 +KBDB_DB_USER=KB_USER +KBDB_DB_PASSWORD=... +KBDB_DB_DSN=... +KBDB_DB_WALLET_LOCATION=... +KBDB_DB_WALLET_PASSWORD=... +KBDB_SEARCH_TYPE=hybrid +KBDB_NODE_EXPANSION=true +KBDB_NODE_MAX_RELATED=8 +KBDB_GRAPH_CROSS_REF=false +KBDB_MAX_CROSS_REF_HOPS=1 +KBDB_DOCUMENT_TYPE=customer_safe +KBDB_METADATA_JSON= +KBDB_MIN_SCORE= +``` + +Quando `RAG_PROVIDER=kbdb`, `KBDB_DB_USER`, `KBDB_DB_PASSWORD` e `KBDB_DB_DSN` são obrigatórios. O KBDB usa conexão isolada porque pode residir em outro Autonomous. `KBDB_DB_DSN` segue a mesma semântica de `ADB_DSN`: use o alias TNS existente no `tnsnames.ora` da wallet indicada por `KBDB_DB_WALLET_LOCATION`, e não uma URL `tcps://...`. + +## Isolamento e compatibilidade + +- `RAG_PROVIDER=standard` não importa nem conecta ao KBDB. +- `RAG_PROVIDER=kbdb` não instancia vector/graph stores do RAG padrão. +- Ingestão por `RagService.add_documents()` não é permitida no modo KBDB: deve passar pelo pipeline/publicação KBDB. +- Query rewrite e context compression continuam opcionais e são aplicados pela camada comum do framework. +- `AgentRuntimeMixin._retrieve_rag_context()` e os agentes permanecem inalterados. +- Falhas do KBDB seguem a semântica existente do framework: retrieval é evidência auxiliar e a exceção é convertida em metadata técnica sem derrubar a jornada. + + +## Resposta direta de tool e RAG + +O framework não considera mais que um resultado MCP estruturado é, por si só, uma resposta suficiente ao usuário. + +Uma política `response.renderer` define somente **como** apresentar o resultado. Ela não encerra o fluxo antes de RAG/LLM. Para uma tool deliberadamente produzir uma resposta final direta, a aplicação deve declarar explicitamente: + +```yaml +response: + mode: renderer + renderer: meu.renderer + direct: true +``` + +Sem `direct: true`, o resultado da tool permanece como evidência MCP e o fluxo segue para `_retrieve_rag_context()` e composição LLM. Isso permite, por exemplo, que uma consulta operacional de plano seja combinada com conhecimento documental do KBDB quando a pergunta pedir regras, políticas ou explicações. + +O core do framework não possui fallback por nome de tool (`consultar_plano`, `consultar_pedido`, etc.). Regras de apresentação pertencem à aplicação/domínio. + + +## Suficiência MCP e grounding + +Um resultado MCP bem-sucedido **não** faz o framework pular RAG automaticamente. +O domínio só pode declarar suficiência documental explicitamente no payload com +`rag_sufficient=true` ou `knowledge_sufficient=true`. Essa decisão é genérica e +não depende do nome da tool nem de palavras-chave de telecom/retail. + +No provider `kbdb`, `KBDB_GROUNDED_ONLY=true` é o padrão. Quando a busca KBDB +retorna vazia, bloqueada ou com erro, a composição LLM pode usar fatos comprovados +por MCP/business context, mas não pode completar a parte documental com conhecimento +paramétrico do modelo. Deve informar que não há evidência suficiente na base. + +Eventos do ProductAgent registram `IC.PRODUCT_RAG_CONTEXT_EVALUATED` em toda +tentativa/decisão e `IC.PRODUCT_RAG_CONTEXT_RETRIEVED` somente quando há contexto +recuperado. Os metadados incluem `provider`, `status`, `document_count`, `reason`, +`error`, `query`, `namespace` e `latency_ms`. diff --git a/libs/agent_framework/src/agent_framework.egg-info/SOURCES.txt b/libs/agent_framework/src/agent_framework.egg-info/SOURCES.txt index 4867a38..9499deb 100644 --- a/libs/agent_framework/src/agent_framework.egg-info/SOURCES.txt +++ b/libs/agent_framework/src/agent_framework.egg-info/SOURCES.txt @@ -190,6 +190,7 @@ src/agent_framework/rag/__init__.py src/agent_framework/rag/embedding_provider.py src/agent_framework/rag/graph_store.py src/agent_framework/rag/ingest.py +src/agent_framework/rag/kbdb_service.py src/agent_framework/rag/rag_service.py src/agent_framework/rag/vector_store.py src/agent_framework/repositories/__init__.py @@ -215,6 +216,7 @@ src/agent_framework/supervisor/router_supervisor.py src/agent_framework/supervisor/supervisor.py src/agent_framework/workflows/__init__.py src/agent_framework/workflows/graph.py +src/agent_framework/workflows/input_contract.py src/agent_framework/workflows/models.py src/agent_framework/workflows/registry.py src/agent_framework/workflows/repository.py diff --git a/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc index cd74785..4950c71 100644 Binary files a/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..71d6404 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc new file mode 100644 index 0000000..4929616 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-313.pyc index 25ef057..ba44907 100644 Binary files a/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-314.pyc b/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-314.pyc new file mode 100644 index 0000000..c57d7a9 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-313.pyc index deec690..2550c75 100644 Binary files a/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-314.pyc b/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-314.pyc new file mode 100644 index 0000000..5769340 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc index 034108a..1d34064 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..db730fd Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-313.pyc index f451e26..ce6ebcb 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-314.pyc new file mode 100644 index 0000000..4a7eec8 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-313.pyc index a5123b3..64a4f8a 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-314.pyc new file mode 100644 index 0000000..2fd78d8 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-313.pyc index 4448806..e39f099 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-314.pyc new file mode 100644 index 0000000..dbb0b1e Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-313.pyc index 5d34ee7..beafe48 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-314.pyc new file mode 100644 index 0000000..1b2e073 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-313.pyc index 1840490..c9fa989 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-314.pyc new file mode 100644 index 0000000..9311639 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_sequence.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_sequence.cpython-313.pyc index 73f4d2b..617999a 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_sequence.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_sequence.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_sequence.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_sequence.cpython-314.pyc new file mode 100644 index 0000000..1f849c9 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_sequence.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/__init__.cpython-313.pyc index 96503a4..059f0dc 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..801eb7f Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-313.pyc index 3fe24d1..deabfe0 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-314.pyc new file mode 100644 index 0000000..4585713 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/langfuse.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/langfuse.cpython-313.pyc index 267f689..567b0d6 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/langfuse.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/langfuse.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/langfuse.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/langfuse.cpython-314.pyc new file mode 100644 index 0000000..9ae90a6 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/langfuse.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/oci_streaming.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/oci_streaming.cpython-313.pyc index fa6628b..08357c6 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/oci_streaming.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/oci_streaming.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/oci_streaming.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/oci_streaming.cpython-314.pyc new file mode 100644 index 0000000..db5b668 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/oci_streaming.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-313.pyc index 314aa91..7d68a98 100644 Binary files a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-314.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-314.pyc new file mode 100644 index 0000000..7bb19f1 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/billing/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/billing/__pycache__/__init__.cpython-313.pyc index 3724131..44d75e9 100644 Binary files a/libs/agent_framework/src/agent_framework/billing/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/billing/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/billing/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/billing/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..6ef6f8c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/billing/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-313.pyc index b79a115..3517624 100644 Binary files a/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-314.pyc b/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-314.pyc new file mode 100644 index 0000000..86878d2 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-313.pyc index f4bcd6b..f520e90 100644 Binary files a/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..6be3d8d Binary files /dev/null and b/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/cache/__pycache__/cache.cpython-313.pyc b/libs/agent_framework/src/agent_framework/cache/__pycache__/cache.cpython-313.pyc index 893ae4e..9a17468 100644 Binary files a/libs/agent_framework/src/agent_framework/cache/__pycache__/cache.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/cache/__pycache__/cache.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/cache/__pycache__/cache.cpython-314.pyc b/libs/agent_framework/src/agent_framework/cache/__pycache__/cache.cpython-314.pyc new file mode 100644 index 0000000..d100dad Binary files /dev/null and b/libs/agent_framework/src/agent_framework/cache/__pycache__/cache.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-313.pyc index b988b7e..4378e5f 100644 Binary files a/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..12318df Binary files /dev/null and b/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-313.pyc index a589806..93d4070 100644 Binary files a/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-314.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-314.pyc new file mode 100644 index 0000000..de54881 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-313.pyc index 53aff71..953d8ab 100644 Binary files a/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-314.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-314.pyc new file mode 100644 index 0000000..aca2452 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-313.pyc index e9305f1..820a3cd 100644 Binary files a/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-314.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-314.pyc new file mode 100644 index 0000000..52b31d1 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc index deb08c3..bc9e8de 100644 Binary files a/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-314.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-314.pyc new file mode 100644 index 0000000..29ce861 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/transcription.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/transcription.cpython-313.pyc index 92a9594..ec90810 100644 Binary files a/libs/agent_framework/src/agent_framework/channels/__pycache__/transcription.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/channels/__pycache__/transcription.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/channels/__pycache__/transcription.cpython-314.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/transcription.cpython-314.pyc new file mode 100644 index 0000000..bf3e526 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/channels/__pycache__/transcription.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/__init__.cpython-313.pyc index 9834e10..e6c3d6a 100644 Binary files a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..0f1a5aa Binary files /dev/null and b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-313.pyc index 68ed373..d642f11 100644 Binary files a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-314.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-314.pyc new file mode 100644 index 0000000..d453289 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-313.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-313.pyc index bb18688..cef92f3 100644 Binary files a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-314.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-314.pyc new file mode 100644 index 0000000..7356750 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/checkpoints/langgraph_saver.py b/libs/agent_framework/src/agent_framework/checkpoints/langgraph_saver.py index 468338c..18dac4a 100644 --- a/libs/agent_framework/src/agent_framework/checkpoints/langgraph_saver.py +++ b/libs/agent_framework/src/agent_framework/checkpoints/langgraph_saver.py @@ -18,6 +18,7 @@ returned using CheckpointTuple; otherwise a simple dict is returned for tests. """ import asyncio +import base64 import json import uuid from typing import Any, AsyncIterator, Iterator @@ -94,6 +95,200 @@ def _strict_json_value(value: Any, *, path: str = "$") -> Any: ) + +_TYPED_SERDE_MARKER = "__agent_framework_langgraph_typed__" + + +def _is_langgraph_interrupt(value: Any) -> bool: + """Return True only for LangGraph's native Interrupt primitive. + + Keep this deliberately narrow. The repository contract remains strict JSON + everywhere else so an unrelated future runtime object cannot silently change + the durable checkpoint format. + """ + cls = type(value) + return cls.__module__ == "langgraph.types" and cls.__qualname__ == "Interrupt" + + +def _typed_serde_envelope(serializer: Any, value: Any, *, path: str) -> dict[str, Any]: + dumps_typed = getattr(serializer, "dumps_typed", None) + if not callable(dumps_typed): + raise TypeError(f"Serializer LangGraph não suporta dumps_typed em {path}") + type_name, payload = dumps_typed(value) + if not isinstance(payload, (bytes, bytearray)): + raise TypeError( + f"Serializer LangGraph retornou payload inválido em {path}: " + f"{type(payload).__module__}.{type(payload).__qualname__}" + ) + return { + _TYPED_SERDE_MARKER: True, + "type": str(type_name), + "data": base64.b64encode(bytes(payload)).decode("ascii"), + } + + + + +def _encode_checkpoint_value( + serializer: Any, + value: Any, + *, + path: str = "$.checkpoint", + in_channel_values: bool = False, + in_interrupt_channel: bool = False, +) -> Any: + """Serialize the checkpoint without widening its historical JSON contract. + + The only typed exception is LangGraph's native ``Interrupt`` and only while + traversing the special ``__interrupt__`` channel under ``channel_values``. + Every other checkpoint value keeps the strict-JSON behavior, so future + runtime/business objects cannot silently start using typed serde. + """ + if value is None or isinstance(value, (str, int, float, bool)): + return value + if isinstance(value, dict): + out: dict[str, Any] = {} + for key, item in value.items(): + skey = str(key) + child_in_channel_values = in_channel_values or ( + path == "$.checkpoint" and skey == "channel_values" + ) + child_in_interrupt_channel = in_interrupt_channel or ( + child_in_channel_values and skey == "__interrupt__" + ) + out[skey] = _encode_checkpoint_value( + serializer, + item, + path=f"{path}.{skey}", + in_channel_values=child_in_channel_values, + in_interrupt_channel=child_in_interrupt_channel, + ) + return out + if isinstance(value, (list, tuple)): + return [ + _encode_checkpoint_value( + serializer, + item, + path=f"{path}[{idx}]", + in_channel_values=in_channel_values, + in_interrupt_channel=in_interrupt_channel, + ) + for idx, item in enumerate(value) + ] + if in_channel_values and in_interrupt_channel and _is_langgraph_interrupt(value): + return _typed_serde_envelope(serializer, value, path=path) + return _strict_json_value(value, path=path) + + +def _decode_checkpoint_value( + serializer: Any, + value: Any, + *, + path: str = "$.checkpoint", + in_channel_values: bool = False, + in_interrupt_channel: bool = False, +) -> Any: + """Inverse of :func:`_encode_checkpoint_value`, with the same narrow scope.""" + if isinstance(value, dict): + if in_channel_values and in_interrupt_channel and value.get(_TYPED_SERDE_MARKER) is True: + loads_typed = getattr(serializer, "loads_typed", None) + if not callable(loads_typed): + raise TypeError("Serializer LangGraph não suporta loads_typed") + type_name = value.get("type") + raw = value.get("data") + if not isinstance(type_name, str) or not isinstance(raw, str): + raise TypeError(f"Envelope de serialização LangGraph inválido em {path}") + return loads_typed((type_name, base64.b64decode(raw.encode("ascii")))) + out: dict[str, Any] = {} + for key, item in value.items(): + skey = str(key) + child_in_channel_values = in_channel_values or ( + path == "$.checkpoint" and skey == "channel_values" + ) + child_in_interrupt_channel = in_interrupt_channel or ( + child_in_channel_values and skey == "__interrupt__" + ) + out[skey] = _decode_checkpoint_value( + serializer, + item, + path=f"{path}.{skey}", + in_channel_values=child_in_channel_values, + in_interrupt_channel=child_in_interrupt_channel, + ) + return out + if isinstance(value, list): + return [ + _decode_checkpoint_value( + serializer, + item, + path=f"{path}[{idx}]", + in_channel_values=in_channel_values, + in_interrupt_channel=in_interrupt_channel, + ) + for idx, item in enumerate(value) + ] + return value + +def _encode_pending_write_value( + serializer: Any, + value: Any, + *, + path: str, + in_interrupt_channel: bool = False, +) -> Any: + """Serialize pending writes with a narrowly-scoped Interrupt exception. + + ``Interrupt`` is accepted only in LangGraph's special ``__interrupt__`` + branch (either the write channel itself or a nested ``__interrupt__`` key). + Other non-JSON objects still fail loudly. + """ + if value is None or isinstance(value, (str, int, float, bool)): + return value + if isinstance(value, dict): + out: dict[str, Any] = {} + for key, item in value.items(): + skey = str(key) + child_interrupt = in_interrupt_channel or skey == "__interrupt__" + out[skey] = _encode_pending_write_value( + serializer, + item, + path=f"{path}.{skey}", + in_interrupt_channel=child_interrupt, + ) + return out + if isinstance(value, (list, tuple)): + return [ + _encode_pending_write_value( + serializer, + item, + path=f"{path}[{idx}]", + in_interrupt_channel=in_interrupt_channel, + ) + for idx, item in enumerate(value) + ] + if in_interrupt_channel and _is_langgraph_interrupt(value): + return _typed_serde_envelope(serializer, value, path=path) + return _strict_json_value(value, path=path) + + +def _serde_decode(serializer: Any, value: Any) -> Any: + """Restore values encoded by :func:`_serde_encode` recursively.""" + if isinstance(value, dict): + if value.get(_TYPED_SERDE_MARKER) is True: + loads_typed = getattr(serializer, "loads_typed", None) + if not callable(loads_typed): + raise TypeError("Serializer LangGraph não suporta loads_typed") + type_name = value.get("type") + raw = value.get("data") + if not isinstance(type_name, str) or not isinstance(raw, str): + raise TypeError("Envelope de serialização LangGraph inválido") + return loads_typed((type_name, base64.b64decode(raw.encode("ascii")))) + return {key: _serde_decode(serializer, item) for key, item in value.items()} + if isinstance(value, list): + return [_serde_decode(serializer, item) for item in value] + return value + + def _normalize_checkpoint(checkpoint: Any) -> dict[str, Any]: checkpoint = _parse_legacy_json_container(checkpoint, dict) if not isinstance(checkpoint, dict): @@ -277,6 +472,7 @@ class RepositoryCheckpointSaver(BaseCheckpointSaver): def __init__(self, settings, repository=None): super().__init__() + self.serde = getattr(self, "serde", None) self.settings = settings self.repository = repository or create_checkpoint_repository(settings) self._loop: asyncio.AbstractEventLoop | None = None @@ -302,8 +498,10 @@ class RepositoryCheckpointSaver(BaseCheckpointSaver): # Second-stage protection: never re-bind the full persisted RunnableConfig. # Rebuild only the durable identifiers, as official LangGraph savers do. config = _canonical_checkpoint_config(payload, request_config) - checkpoint = _strip_runtime_refs(_normalize_checkpoint(payload.get("checkpoint") or {})) - metadata = _strip_runtime_refs(_normalize_metadata(payload.get("metadata") or {})) + checkpoint_value = _decode_checkpoint_value(self.serde, payload.get("checkpoint") or {}) + metadata_value = payload.get("metadata") or {} + checkpoint = _strip_runtime_refs(_normalize_checkpoint(checkpoint_value)) + metadata = _strip_runtime_refs(_normalize_metadata(metadata_value)) raw_parent_config = payload.get("parent_config") if isinstance(raw_parent_config, dict): parent_payload = { @@ -317,8 +515,9 @@ class RepositoryCheckpointSaver(BaseCheckpointSaver): parent_config = _canonical_checkpoint_config(parent_payload) else: parent_config = None + pending_value = _serde_decode(self.serde, payload.get("pending_writes") or []) pending_writes = _normalize_pending_writes( - _strip_runtime_refs(payload.get("pending_writes") or []) + _strip_runtime_refs(pending_value) ) try: from langgraph.checkpoint.base import CheckpointTuple @@ -359,7 +558,7 @@ class RepositoryCheckpointSaver(BaseCheckpointSaver): await self.repository.put(thread_id, { "thread_id": thread_id, "config": _strict_json_value(next_config, path="$.config"), - "checkpoint": _strict_json_value(_strip_runtime_refs(_normalize_checkpoint(checkpoint)), path="$.checkpoint"), + "checkpoint": _encode_checkpoint_value(self.serde, _strip_runtime_refs(_normalize_checkpoint(checkpoint)), path="$.checkpoint"), "metadata": _strict_json_value(_strip_runtime_refs(_normalize_metadata(metadata or {})), path="$.metadata"), "new_versions": _strict_json_value(_strip_runtime_refs(new_versions or {}), path="$.new_versions"), "checkpoint_id": checkpoint_id, @@ -410,7 +609,12 @@ class RepositoryCheckpointSaver(BaseCheckpointSaver): "task_id": task_id, "task_path": task_path, "channel": channel, - "value": _strict_json_value(durable_value, path=f"$.pending_writes[{task_id}].{channel}"), + "value": _encode_pending_write_value( + self.serde, + durable_value, + path=f"$.pending_writes[{task_id}].{channel}", + in_interrupt_channel=(str(channel) == "__interrupt__"), + ), }) latest["pending_writes"] = pending await self.repository.put(thread_id, latest) diff --git a/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-313.pyc index 411fc5a..620bbed 100644 Binary files a/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..fc23523 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-313.pyc index d94f1d7..3ba77e2 100644 Binary files a/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-314.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-314.pyc new file mode 100644 index 0000000..7e4aa3f Binary files /dev/null and b/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-313.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-313.pyc index 05536b0..24c2611 100644 Binary files a/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-314.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-314.pyc new file mode 100644 index 0000000..c5c6565 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/config/settings.py b/libs/agent_framework/src/agent_framework/config/settings.py index 45da3f9..5cab2f1 100644 --- a/libs/agent_framework/src/agent_framework/config/settings.py +++ b/libs/agent_framework/src/agent_framework/config/settings.py @@ -103,12 +103,32 @@ class Settings(BaseSettings): ENABLE_REDIS_CACHE: bool = False CACHE_KEY_PREFIX: str = 'agentfw' + # RAG backend selector. 'standard' preserves the existing framework RAG; + # 'kbdb' consumes the enterprise KBDB stable serving facade without changing agents. + RAG_PROVIDER: Literal['standard','kbdb'] = 'standard' VECTOR_STORE_PROVIDER: Literal['memory','sqlite','autonomous','oracle','mongodb'] = 'memory' GRAPH_STORE_PROVIDER: Literal['memory','autonomous','oracle'] = 'memory' ORACLE_GRAPH_NAME: str = 'AGENTFW_GRAPH' ORACLE_GRAPH_AUTO_CREATE: bool = False RAG_TOP_K: int = 5 + KBDB_DB_USER: str | None = None + KBDB_DB_PASSWORD: str | None = None + KBDB_DB_DSN: str | None = None + KBDB_DB_WALLET_LOCATION: str | None = None + KBDB_DB_WALLET_PASSWORD: str | None = None + KBDB_SEARCH_TYPE: Literal['hybrid','vector','keyword'] = 'hybrid' + KBDB_NODE_EXPANSION: bool = True + KBDB_NODE_MAX_RELATED: int = 8 + KBDB_GRAPH_CROSS_REF: bool = False + KBDB_MAX_CROSS_REF_HOPS: int = 1 + KBDB_DOCUMENT_TYPE: str | None = 'customer_safe' + KBDB_METADATA_JSON: str | None = None + KBDB_MIN_SCORE: float | None = None + # MCP só pula retrieval quando declarar explicitamente rag_sufficient/knowledge_sufficient. SKIP_RAG_WHEN_MCP_SUFFICIENT: bool = True + # Preserva comportamento legado do RAG standard; KBDB enterprise é grounded-only por padrão. + RAG_GROUNDED_ONLY: bool = False + KBDB_GROUNDED_ONLY: bool = True ENABLE_RAG_QUERY_REWRITE: bool = False ENABLE_RAG_CONTEXT_COMPRESSION: bool = False ENABLE_RAG_GENERATION: bool = False diff --git a/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc index 2f31bcb..aa1c7ad 100644 Binary files a/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..653eb0a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc index 74fb001..c05807e 100644 Binary files a/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-314.pyc b/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-314.pyc new file mode 100644 index 0000000..82a2a06 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-313.pyc index 23860d7..9c16e82 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..78bb0ad Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc index 2edc15f..6d2e121 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-314.pyc new file mode 100644 index 0000000..bb9ca22 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc index a9157af..170c01a 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-314.pyc new file mode 100644 index 0000000..66e624f Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc index 39187c0..32d61ea 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-314.pyc new file mode 100644 index 0000000..773b714 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-313.pyc index 28ff7e9..16ca8d9 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-314.pyc new file mode 100644 index 0000000..85d2efc Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc index 58271f2..5bc0873 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-314.pyc new file mode 100644 index 0000000..f3de0d0 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc index 5663c4b..160e65c 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-314.pyc new file mode 100644 index 0000000..00e048c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc index a4f78f1..e54d65b 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-314.pyc new file mode 100644 index 0000000..c6af641 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc index e30bb5f..b4ab329 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-314.pyc new file mode 100644 index 0000000..ad98215 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-313.pyc index a73de07..fad910e 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-314.pyc new file mode 100644 index 0000000..1f21200 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-313.pyc index a3f7962..5fde2c2 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-314.pyc new file mode 100644 index 0000000..2b6383c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-313.pyc index f8bb661..301eb4e 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-314.pyc new file mode 100644 index 0000000..84103c5 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-313.pyc index ade4d43..cdb5396 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-314.pyc new file mode 100644 index 0000000..ada5519 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc index 784931e..9fb8ff0 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..0e2103d Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-313.pyc index 4eb13fa..213473b 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-314.pyc new file mode 100644 index 0000000..6335a22 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-313.pyc index de98b7b..16e8514 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-314.pyc new file mode 100644 index 0000000..57e5e6a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-313.pyc index 789cc88..a7fdcd9 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-314.pyc new file mode 100644 index 0000000..9a38d41 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-313.pyc index 25f6e32..645c72e 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-314.pyc new file mode 100644 index 0000000..bd35ca0 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-313.pyc index 05cedc1..1f2be21 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-314.pyc new file mode 100644 index 0000000..6c7b8d2 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-313.pyc index 308a422..3bf7ebf 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-314.pyc new file mode 100644 index 0000000..f8f9d1c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc index 3f9be8a..15d3d08 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-314.pyc new file mode 100644 index 0000000..d220e22 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc index 4c92a6e..5248f14 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-314.pyc new file mode 100644 index 0000000..b66611a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-313.pyc index 94358bc..340328e 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-314.pyc new file mode 100644 index 0000000..f32bdd7 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc index 5e26da3..3022688 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..2eb5407 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc index f593963..2c49d3a 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-314.pyc new file mode 100644 index 0000000..2e8a98c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc index 6205861..f64d5da 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-314.pyc new file mode 100644 index 0000000..8aa6d65 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-313.pyc index ca8b372..c80d5cd 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-314.pyc new file mode 100644 index 0000000..6a20d0f Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-313.pyc index 0fbad9d..c36a2d4 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-314.pyc new file mode 100644 index 0000000..3481c08 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc index 5fd4841..f1b478f 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-314.pyc new file mode 100644 index 0000000..3974ac0 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-313.pyc index f5c3f71..ff0e3e7 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-314.pyc new file mode 100644 index 0000000..4274642 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-313.pyc index aad36c5..dddc419 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-314.pyc new file mode 100644 index 0000000..efcf677 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc index 87c729a..1b8a9d3 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-314.pyc new file mode 100644 index 0000000..32c3c9b Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc index 19f9644..12cab79 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-314.pyc new file mode 100644 index 0000000..5eebc60 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-313.pyc index 5dc208b..ecd8196 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-314.pyc new file mode 100644 index 0000000..e96207b Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-313.pyc index a5804aa..d329b33 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-314.pyc new file mode 100644 index 0000000..e13b37a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc index 96c0db9..fd5a6a0 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-314.pyc new file mode 100644 index 0000000..5d56972 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-313.pyc index 4161dd3..278bb70 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-314.pyc new file mode 100644 index 0000000..451b272 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/ausencia_oferta_proativa.py b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/ausencia_oferta_proativa.py index 13687ab..88d977e 100644 --- a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/ausencia_oferta_proativa.py +++ b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/ausencia_oferta_proativa.py @@ -1,6 +1,6 @@ def build_aoferta_prompt(text: str, context: str = "") -> str: return f""" -Voce e um auditor de atendimento ao cliente do provedor. Decida se a fala do agente +Voce e um auditor de atendimento ao cliente da TIM. Decida se a fala do agente abaixo e oferta proativa indevida. Voce julga SO acao TRANSACIONAL: cancelar, ajustar, contestar, creditar, devolver, @@ -21,6 +21,16 @@ Decida na ordem, PARE no primeiro match: permissao para explicar/mostrar ("posso te mostrar o motivo?") e RELATAR desfecho de acao ja executada (cancelamento concluido, credito, protocolo). +1b. COLETA DE PARAMETROS / CLARIFICACAO NAO E ACAO TRANSACIONAL. Se a fala + apenas pede um dado necessario para continuar uma solicitacao ja em andamento + (valor, data, servico, produto, cobranca, mes, motivo ou outro dado de negocio), + -> allowed=true. Julgue SOMENTE a fala atual: nao antecipe a acao que PODERA + ocorrer depois que o dado for informado. Pedir um parametro nao cancela, nao + contesta, nao ajusta, nao credita, nao devolve e nao concede nada. + Esta regra vale mesmo quando o alvo citado anteriormente e plano/linha ou outro + alvo que seria bloqueado no passo 2b caso a fala estivesse efetivamente oferecendo + ou executando uma acao transacional. + 2. A fala oferece PROCEDIMENTO que o agente nao executa: "abrir analise", "encaminhar para verificacao", "abrir chamado", "verificar e retornar", "registrar para retorno", "encaminhar ao setor responsavel" @@ -127,6 +137,21 @@ Exemplos (as falas do agente sao as saidas canonicas do orquestrador): [assistant] Entendo que o desconto de R$ 10,00 não foi aplicado. Gostaria que eu contestasse esse valor? {{"allowed": false, "reason": "'Gostaria que eu contestasse esse valor?': desconto e valor que o agente concede — como credito ou isencao —, o pedido nao libera e trocar o verbo por contestar nao muda o alvo (passo 2b)"}} +# 10 - coleta de parametro de uma transacao em andamento NAO e oferta (passo 1b) +[user] nao contratei TIM CTRL Redes Sociais 8.0 +[assistant] Para prosseguir, informe valor. +{{"allowed": true, "reason": ""}} + +# 11 - pedir dado de negocio para continuar NAO antecipa a acao futura (passo 1b) +[user] quero contestar essa cobranca +[assistant] Qual foi o valor da cobranca? +{{"allowed": true, "reason": ""}} + +# 12 - continua proibido oferecer a acao sobre plano/linha (passo 2b) +[user] nao contratei TIM CTRL Redes Sociais 8.0 +[assistant] Posso cancelar esse plano para voce. +{{"allowed": false, "reason": "'Posso cancelar esse plano para voce.': oferece cancelamento de plano/linha, alvo de dano comercial (passo 2b)"}} + ------------------------------------{context} Resposta a avaliar: {text} diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-313.pyc index a71492a..bf039b9 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..1726df7 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-313.pyc index f8db266..bcc4b67 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-314.pyc new file mode 100644 index 0000000..0e6fb0c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-313.pyc index 6bfa669..601538e 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-314.pyc new file mode 100644 index 0000000..cd8b0c9 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc index 522e165..426217f 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-314.pyc new file mode 100644 index 0000000..398e18a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc index 9cf7e4a..458a998 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-314.pyc new file mode 100644 index 0000000..3c34903 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc index 85dd15e..803056f 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-314.pyc new file mode 100644 index 0000000..34bb605 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-313.pyc index c5f6bb3..9576f69 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-314.pyc new file mode 100644 index 0000000..1da544c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-313.pyc index 72cf505..1bd263f 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-314.pyc new file mode 100644 index 0000000..807ecfe Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-313.pyc index e4886f3..e5b5f25 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-314.pyc new file mode 100644 index 0000000..00de543 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc index 3e8b4d3..5d1f48c 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..29d0b95 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc index 2cbd176..2eee30e 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-314.pyc new file mode 100644 index 0000000..77f5938 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/pinj_patterns.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/pinj_patterns.cpython-313.pyc index e47902a..b1a0594 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/pinj_patterns.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/pinj_patterns.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/pinj_patterns.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/pinj_patterns.cpython-314.pyc new file mode 100644 index 0000000..553ba62 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/pinj_patterns.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-313.pyc index 021976a..9f4b74b 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-314.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-314.pyc new file mode 100644 index 0000000..0e59782 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/identity/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/__init__.cpython-313.pyc index 09f9ffe..2225db2 100644 Binary files a/libs/agent_framework/src/agent_framework/identity/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/identity/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/identity/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..94d0a62 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/identity/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-313.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-313.pyc index f9247b5..2e18081 100644 Binary files a/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-314.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-314.pyc new file mode 100644 index 0000000..01486b5 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/identity/__pycache__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/models.cpython-313.pyc index 4c3f3db..692d923 100644 Binary files a/libs/agent_framework/src/agent_framework/identity/__pycache__/models.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/identity/__pycache__/models.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/identity/__pycache__/models.cpython-314.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/models.cpython-314.pyc new file mode 100644 index 0000000..42bb4a3 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/identity/__pycache__/models.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-313.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-313.pyc index 8e4c636..f57e48a 100644 Binary files a/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-314.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-314.pyc new file mode 100644 index 0000000..33d8536 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-313.pyc index ba5a5f7..0e63775 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..8d81487 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc index 72d653d..ff3e57d 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-314.pyc new file mode 100644 index 0000000..7a77062 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-313.pyc index 58bc8a5..03f02ab 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..cd28934 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-313.pyc index 0c59cbd..721ad48 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-314.pyc new file mode 100644 index 0000000..b1a58d0 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/__init__.cpython-313.pyc index 9ee624a..f323acb 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..524d2fa Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-313.pyc index 8cb3e8c..aba5f04 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-314.pyc new file mode 100644 index 0000000..d4fa79e Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-313.pyc index 871ad16..9d2d08e 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-314.pyc new file mode 100644 index 0000000..f7caec6 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-313.pyc index e2648af..f5734ca 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-314.pyc new file mode 100644 index 0000000..5225c54 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-313.pyc index 201d849..b517b93 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-314.pyc new file mode 100644 index 0000000..d37df00 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-313.pyc index 04ec9f9..352b02a 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-314.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-314.pyc new file mode 100644 index 0000000..82d7877 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-313.pyc index cad4297..953fbdb 100644 Binary files a/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..92b0662 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-313.pyc index e7d38a7..3fc0e83 100644 Binary files a/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-314.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-314.pyc new file mode 100644 index 0000000..612655a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-313.pyc index 54662ca..99557e8 100644 Binary files a/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-314.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-314.pyc new file mode 100644 index 0000000..763301f Binary files /dev/null and b/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc index e7edb4c..254b973 100644 Binary files a/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-314.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-314.pyc new file mode 100644 index 0000000..3b8a787 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-313.pyc new file mode 100644 index 0000000..bffe0c2 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-314.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-314.pyc new file mode 100644 index 0000000..6ab0fe2 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/__init__.cpython-313.pyc index 0c921a8..5a278b7 100644 Binary files a/libs/agent_framework/src/agent_framework/mcp/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..b9ca1a8 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-313.pyc index be1bf7e..d3d049d 100644 Binary files a/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-314.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-314.pyc new file mode 100644 index 0000000..a28d6d0 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-313.pyc index 966e33d..12989e6 100644 Binary files a/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-314.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-314.pyc new file mode 100644 index 0000000..dd643d2 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-313.pyc index 8b44c2d..51e8f3d 100644 Binary files a/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-314.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-314.pyc new file mode 100644 index 0000000..9bd592a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-313.pyc index 9f43626..c354322 100644 Binary files a/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-314.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-314.pyc new file mode 100644 index 0000000..861d005 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-313.pyc index 9243caa..92e1fbf 100644 Binary files a/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-314.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-314.pyc new file mode 100644 index 0000000..ca2966a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-313.pyc index 2becb01..7ae88b6 100644 Binary files a/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..cf4b775 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_extractor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_extractor.cpython-313.pyc index 8062ace..6f94b5c 100644 Binary files a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_extractor.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_extractor.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_extractor.cpython-314.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_extractor.cpython-314.pyc new file mode 100644 index 0000000..0346f89 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_extractor.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-313.pyc index f887600..84cf39d 100644 Binary files a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-314.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-314.pyc new file mode 100644 index 0000000..828229c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-313.pyc index 05dbb4e..a317c2d 100644 Binary files a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-314.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-314.pyc new file mode 100644 index 0000000..4d8e11a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-313.pyc index a1cfcae..1a322bb 100644 Binary files a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-314.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-314.pyc new file mode 100644 index 0000000..c8ab6e0 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-313.pyc index 5cca607..4dc396c 100644 Binary files a/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-314.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-314.pyc new file mode 100644 index 0000000..d5f245c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc index 049ad41..a27f27e 100644 Binary files a/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-314.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-314.pyc new file mode 100644 index 0000000..046b1d9 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-313.pyc index a8ce304..55be2b9 100644 Binary files a/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-314.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-314.pyc new file mode 100644 index 0000000..8e8c46b Binary files /dev/null and b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-313.pyc index 6e18c2e..10af14f 100644 Binary files a/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..158dc31 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-313.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-313.pyc index c840c51..f3e25cc 100644 Binary files a/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-314.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-314.pyc new file mode 100644 index 0000000..669b49e Binary files /dev/null and b/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-313.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-313.pyc index f302fad..cbe3fd2 100644 Binary files a/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-314.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-314.pyc new file mode 100644 index 0000000..27631f2 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-313.pyc index 046c99a..16ebb80 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..48009c3 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-313.pyc new file mode 100644 index 0000000..5d5e75e Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-314.pyc new file mode 100644 index 0000000..721e0f6 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-313.pyc index 4c822b0..466aa0e 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-314.pyc new file mode 100644 index 0000000..283fa67 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-313.pyc index 53b9e9d..5306ee2 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-314.pyc new file mode 100644 index 0000000..38824de Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/event_bus.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-313.pyc index 2ff7251..3c2dd38 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-314.pyc new file mode 100644 index 0000000..49ca9cd Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-313.pyc index ffe0633..c0ea5e1 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-314.pyc new file mode 100644 index 0000000..054226b Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-313.pyc index 2dc36a2..4efb693 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-314.pyc new file mode 100644 index 0000000..c69dff5 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/judge_events.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-313.pyc index fbc7007..4405b9f 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-314.pyc new file mode 100644 index 0000000..a31f920 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/langgraph_telemetry.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-313.pyc index eaa3aa8..48aaa79 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-314.pyc new file mode 100644 index 0000000..3ff69f7 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-313.pyc index 458ccc5..3b16de7 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-314.pyc new file mode 100644 index 0000000..b42cb53 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_otel.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_otel.cpython-313.pyc index 5d7ac01..2d37d6d 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_otel.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_otel.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_otel.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_otel.cpython-314.pyc new file mode 100644 index 0000000..e5208bb Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_otel.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-313.pyc index d61cc2d..d17dce1 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-314.pyc new file mode 100644 index 0000000..b6d9d52 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-313.pyc index 567886a..25ec585 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-314.pyc new file mode 100644 index 0000000..c82d9a0 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-313.pyc index 987dba7..2c7fb3e 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-314.pyc new file mode 100644 index 0000000..5024ce9 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/telemetry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/telemetry.cpython-313.pyc index 428dcdd..8fd1dd2 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/telemetry.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/telemetry.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/telemetry.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/telemetry.cpython-314.pyc new file mode 100644 index 0000000..328363c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/telemetry.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc index 08f74ea..5ddf5a0 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-314.pyc new file mode 100644 index 0000000..527e74d Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-313.pyc index 0639755..c387e65 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-314.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-314.pyc new file mode 100644 index 0000000..e1b6ed0 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-313.pyc index b6a33cf..5d5ff8b 100644 Binary files a/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..a0dbad2 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-313.pyc b/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-313.pyc index 76997e1..fb3d676 100644 Binary files a/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-314.pyc b/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-314.pyc new file mode 100644 index 0000000..777bee6 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/persistence/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/__init__.cpython-313.pyc index 41b5b31..6b089b7 100644 Binary files a/libs/agent_framework/src/agent_framework/persistence/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/persistence/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/persistence/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..9d1a06e Binary files /dev/null and b/libs/agent_framework/src/agent_framework/persistence/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-313.pyc index 786b42a..c2346eb 100644 Binary files a/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-314.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-314.pyc new file mode 100644 index 0000000..f0ca36f Binary files /dev/null and b/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-313.pyc index 80c7b09..94b1c21 100644 Binary files a/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-314.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-314.pyc new file mode 100644 index 0000000..af469be Binary files /dev/null and b/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/presentation/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/presentation/__pycache__/__init__.cpython-313.pyc index d667b10..46996ad 100644 Binary files a/libs/agent_framework/src/agent_framework/presentation/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/presentation/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/presentation/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/presentation/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..fd21b0d Binary files /dev/null and b/libs/agent_framework/src/agent_framework/presentation/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/presentation/__pycache__/renderers.cpython-313.pyc b/libs/agent_framework/src/agent_framework/presentation/__pycache__/renderers.cpython-313.pyc index 0d68175..e6831cd 100644 Binary files a/libs/agent_framework/src/agent_framework/presentation/__pycache__/renderers.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/presentation/__pycache__/renderers.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/presentation/__pycache__/renderers.cpython-314.pyc b/libs/agent_framework/src/agent_framework/presentation/__pycache__/renderers.cpython-314.pyc new file mode 100644 index 0000000..5f59fa1 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/presentation/__pycache__/renderers.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/__init__.cpython-313.pyc index 970155f..4518f77 100644 Binary files a/libs/agent_framework/src/agent_framework/rag/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/rag/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..a672562 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/rag/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-313.pyc index a326aa9..51d66cf 100644 Binary files a/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-314.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-314.pyc new file mode 100644 index 0000000..64fed76 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-313.pyc index bd793b6..d81ba84 100644 Binary files a/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-314.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-314.pyc new file mode 100644 index 0000000..de809b4 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-313.pyc index dbfa17d..9b33ce3 100644 Binary files a/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-314.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-314.pyc new file mode 100644 index 0000000..e201939 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc new file mode 100644 index 0000000..9fd10d5 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-314.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-314.pyc new file mode 100644 index 0000000..36a91cd Binary files /dev/null and b/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc index a055948..1cb6f4b 100644 Binary files a/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-314.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-314.pyc new file mode 100644 index 0000000..60e42b2 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-313.pyc index b727ba0..4c1891b 100644 Binary files a/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-314.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-314.pyc new file mode 100644 index 0000000..1d46a12 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/rag/kbdb_service.py b/libs/agent_framework/src/agent_framework/rag/kbdb_service.py new file mode 100644 index 0000000..e8422b2 --- /dev/null +++ b/libs/agent_framework/src/agent_framework/rag/kbdb_service.py @@ -0,0 +1,158 @@ +from __future__ import annotations + +import asyncio +import json +import time +from contextlib import contextmanager +from dataclasses import dataclass +from typing import Any + +from .vector_store import VectorDocument + + +def _lob_value(value: Any) -> Any: + return value.read() if hasattr(value, "read") else value + + +@dataclass(frozen=True) +class KbdbOracleSettings: + """Credenciais Oracle exclusivas do Autonomous usado pelo KBDB. + + A semântica é deliberadamente a mesma já usada pelo OracleStore do + framework: ``dsn`` é o alias TNS da wallet, ``config_dir`` e + ``wallet_location`` apontam para a pasta da wallet e ``wallet_password`` + é repassado ao python-oracledb. O KBDB não reutiliza/faz fallback para + ``ADB_*`` porque pode residir em outro Autonomous. + """ + + user: str + password: str + dsn: str + wallet_location: str | None = None + wallet_password: str | None = None + + +class KbdbRagService: + """Enterprise KBDB serving adapter. + + This adapter deliberately integrates only the stable serving facade + PKG_KB_SERVING.SEARCH_KNOWLEDGE_BASE. KBDB ingestion/publication/lifecycle stay + outside the agent runtime. + """ + + def __init__(self, settings, telemetry=None): + self.settings = settings + self.telemetry = telemetry + self.db = KbdbOracleSettings( + user=str(getattr(settings, "KBDB_DB_USER", None) or ""), + password=str(getattr(settings, "KBDB_DB_PASSWORD", None) or ""), + dsn=str(getattr(settings, "KBDB_DB_DSN", None) or ""), + wallet_location=getattr(settings, "KBDB_DB_WALLET_LOCATION", None), + wallet_password=getattr(settings, "KBDB_DB_WALLET_PASSWORD", None), + ) + if not self.db.user or not self.db.password or not self.db.dsn: + raise RuntimeError( + "KBDB_DB_USER, KBDB_DB_PASSWORD e KBDB_DB_DSN são obrigatórios " + "quando RAG_PROVIDER=kbdb" + ) + + @contextmanager + def _connect(self): + """Abre conexão seguindo o mesmo padrão já usado pelo OracleStore. + + Esta implementação é intencionalmente local ao KBDB para não alterar + OracleStore, Long-Term Memory ou qualquer outro consumidor Oracle já + existente no framework. + """ + import oracledb + + oracledb.defaults.fetch_lobs = False + kwargs: dict[str, Any] = {} + if self.db.wallet_location: + kwargs["config_dir"] = self.db.wallet_location + kwargs["wallet_location"] = self.db.wallet_location + if self.db.wallet_password: + kwargs["wallet_password"] = self.db.wallet_password + + conn = oracledb.connect( + user=self.db.user, + password=self.db.password, + dsn=self.db.dsn, + **kwargs, + ) + try: + yield conn + finally: + conn.close() + + def _search_sync(self, query: str, k: int) -> dict[str, Any]: + import oracledb + metadata = self.settings.KBDB_METADATA_JSON + if metadata: + # validate early; procedure expects JSON text + json.loads(metadata) + with self._connect() as conn: + cur = conn.cursor() + if self.settings.KBDB_MIN_SCORE is not None: + cur.callproc("PKG_KB_SERVING.set_min_score", [float(self.settings.KBDB_MIN_SCORE)]) + out = cur.var(oracledb.DB_TYPE_JSON) + cur.callproc("PKG_KB_SERVING.search_knowledge_base", [ + self.settings.KBDB_SEARCH_TYPE, + query, + int(k), + bool(self.settings.KBDB_NODE_EXPANSION), + int(self.settings.KBDB_NODE_MAX_RELATED), + bool(self.settings.KBDB_GRAPH_CROSS_REF), + int(self.settings.KBDB_MAX_CROSS_REF_HOPS), + self.settings.KBDB_DOCUMENT_TYPE or None, + metadata or None, + out, + ]) + value = _lob_value(out.getvalue()) + if isinstance(value, str): + return json.loads(value) + return dict(value or {}) + + async def retrieve(self, query: str, *, namespace: str = "default", k: int | None = None, + graph_node: str | None = None, rewrite: bool = False): + # rewrite is intentionally handled by the framework's RagService wrapper. + from .rag_service import RagResult + start = time.time() + k = k or self.settings.RAG_TOP_K + envelope = await asyncio.to_thread(self._search_sync, query, k) + seeds = {str(s.get("unit_id")): s for s in (envelope.get("seeds") or []) if isinstance(s, dict)} + docs: list[VectorDocument] = [] + for unit in envelope.get("units") or []: + if not isinstance(unit, dict): + continue + unit_id = str(unit.get("unit_id") or unit.get("id") or "") + content = str(unit.get("content") or "").strip() + if not unit_id or not content: + continue + seed = seeds.get(unit_id, {}) + score = float(seed.get("score") or unit.get("score") or 0.0) + docs.append(VectorDocument(id=unit_id, content=content, metadata={**unit, "kbdb_envelope": False}, score=score)) + latency_ms = int((time.time() - start) * 1000) + metadata_out = { + "provider": "kbdb", + "namespace": namespace, + "k": k, + "search_type": envelope.get("search_type") or self.settings.KBDB_SEARCH_TYPE, + "confidence": envelope.get("confidence"), + "low_confidence": bool(envelope.get("low_confidence")), + "warnings": envelope.get("warnings") or [], + "documents": envelope.get("documents") or [], + "top_score": envelope.get("top_score"), + "fallback_reason": envelope.get("fallback_reason"), + "envelope": envelope, + } + if self.telemetry: + await self.telemetry.rag_event("retrieve.completed", query, len(docs), { + "provider": "kbdb", "k": k, "latency_ms": latency_ms, + "confidence": metadata_out["confidence"], "low_confidence": metadata_out["low_confidence"], + "warning_count": len(metadata_out["warnings"]), + }) + return RagResult(query=query, documents=docs, graph_neighbors=[], latency_ms=latency_ms, metadata=metadata_out) + + async def add_documents(self, *args, **kwargs): + raise RuntimeError("RAG_PROVIDER=kbdb é serving-only; ingestão/publicação devem ser executadas pelo pipeline KBDB") diff --git a/libs/agent_framework/src/agent_framework/rag/rag_service.py b/libs/agent_framework/src/agent_framework/rag/rag_service.py index d641fe2..b922606 100644 --- a/libs/agent_framework/src/agent_framework/rag/rag_service.py +++ b/libs/agent_framework/src/agent_framework/rag/rag_service.py @@ -42,10 +42,20 @@ class RagService: self.settings=settings self.telemetry=telemetry self.llm=llm - self.vector_store=create_vector_store(settings, embedding_provider=embedding_provider, telemetry=telemetry) - self.graph_store=create_graph_store(settings, telemetry=telemetry) + self.provider=getattr(settings, 'RAG_PROVIDER', 'standard') + self._kbdb=None + if self.provider == 'kbdb': + from .kbdb_service import KbdbRagService + self._kbdb=KbdbRagService(settings, telemetry=telemetry) + self.vector_store=None + self.graph_store=None + else: + self.vector_store=create_vector_store(settings, embedding_provider=embedding_provider, telemetry=telemetry) + self.graph_store=create_graph_store(settings, telemetry=telemetry) async def add_documents(self, texts: list[str], metadatas: list[dict] | None = None, namespace: str='default') -> list[str]: + if self._kbdb: + return await self._kbdb.add_documents(texts, metadatas=metadatas, namespace=namespace) start=time.time() ids=await self.vector_store.add_texts(texts, metadatas=metadatas, namespace=namespace) if self.telemetry: @@ -57,11 +67,15 @@ class RagService: async def retrieve(self, query: str, *, namespace: str='default', k: int | None=None, graph_node: str | None=None, rewrite: bool = False) -> RagResult: start=time.time(); k=k or self.settings.RAG_TOP_K effective_query = await self.rewrite_query(query, namespace=namespace) if rewrite else query + if self._kbdb: + result = await self._kbdb.retrieve(effective_query, namespace=namespace, k=k, graph_node=graph_node, rewrite=False) + result.metadata.update({'original_query': query, 'rewritten': rewrite and effective_query != query}) + return result docs=await self.vector_store.similarity_search(effective_query, k=k, namespace=namespace) neighbors=[] if graph_node: neighbors=await self.graph_store.neighbors(graph_node) - result=RagResult(query=effective_query, documents=docs, graph_neighbors=neighbors, latency_ms=int((time.time()-start)*1000), metadata={'namespace':namespace,'k':k, 'original_query': query, 'rewritten': rewrite and effective_query != query}) + result=RagResult(query=effective_query, documents=docs, graph_neighbors=neighbors, latency_ms=int((time.time()-start)*1000), metadata={'provider':'standard','namespace':namespace,'k':k, 'original_query': query, 'rewritten': rewrite and effective_query != query}) if self.telemetry: await self.telemetry.rag_event('retrieve.completed', effective_query, len(docs), { 'namespace': namespace, 'k': k, 'latency_ms': result.latency_ms, 'graph_neighbors': len(neighbors), diff --git a/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-313.pyc index 5a01429..2d204cf 100644 Binary files a/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..f5377ba Binary files /dev/null and b/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-313.pyc index f5421a1..d54892f 100644 Binary files a/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-314.pyc b/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-314.pyc new file mode 100644 index 0000000..dc5d5ec Binary files /dev/null and b/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc index 7d0829e..997a762 100644 Binary files a/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..4309a16 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-313.pyc index 4d35623..c767fb3 100644 Binary files a/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-314.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-314.pyc new file mode 100644 index 0000000..ffa86a5 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-313.pyc index eb19e90..89e025c 100644 Binary files a/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-314.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-314.pyc new file mode 100644 index 0000000..297d701 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc index 590a07f..4a94ed8 100644 Binary files a/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-314.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-314.pyc new file mode 100644 index 0000000..eac189e Binary files /dev/null and b/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc index 4ee49bc..b9244ec 100644 Binary files a/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-314.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-314.pyc new file mode 100644 index 0000000..27a483b Binary files /dev/null and b/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/routing/enterprise_router.py b/libs/agent_framework/src/agent_framework/routing/enterprise_router.py index 501e2bf..a2be3e8 100644 --- a/libs/agent_framework/src/agent_framework/routing/enterprise_router.py +++ b/libs/agent_framework/src/agent_framework/routing/enterprise_router.py @@ -10,6 +10,7 @@ from .config_loader import load_intents, load_router_defaults, load_state_polici from .continuity import SemanticRouteContinuity from .models import IntentDefinition, RouteDecision, RouterStatePolicy from agent_framework.runtime.transaction_parameters import extract_transaction_parameters, parse_transaction_confirmation +from agent_framework.workflows.input_contract import match_expected_input logger = logging.getLogger("agent_framework.routing") @@ -71,6 +72,50 @@ class EnterpriseRouter: current_state = explicit_next_state or session.get("metadata", {}).get("workflow_state") text = state.get("sanitized_input") or state.get("user_text") or "" + # A paused conversational workflow owns the next turn when the current + # input satisfies its declarative ``expected_input`` contract. This check + # must happen before route continuity; otherwise a generic reply such as + # "sim" can be misread as END_SESSION instead of resuming the workflow. + pending_workflow = state.get("pending_domain_workflow") + if isinstance(pending_workflow, dict) and pending_workflow.get("execution_id"): + pause = pending_workflow.get("pause") if isinstance(pending_workflow.get("pause"), dict) else {} + expected_input = pause.get("expected_input") if isinstance(pause, dict) else None + matched = match_expected_input(str(text), expected_input) + if matched is not None: + previous = state.get("route_decision") or {} + owner_agent = str( + pending_workflow.get("owner_agent") + or state.get("active_agent") + or previous.get("agent") + or state.get("route") + or self.fallback_agent + ).strip() + owner_intent = str( + pending_workflow.get("owner_intent") + or previous.get("intent") + or state.get("intent") + or f"workflow_resume:{pending_workflow.get('workflow_name') or 'paused'}" + ).strip() + decision = RouteDecision( + route=owner_agent, + agent=owner_agent, + intent=owner_intent, + confidence=1.0, + reason="Entrada consumida pelo contrato expected_input do workflow pausado.", + method="state", + domain=previous.get("domain") or state.get("domain"), + mcp_tools=[str(pending_workflow.get("resume_tool") or "retomar_workflow")], + metadata={ + "route_bypassed": True, + "workflow_resume": True, + "workflow_name": pending_workflow.get("workflow_name"), + "workflow_execution_id": pending_workflow.get("execution_id"), + "normalized_input": matched, + }, + ) + await self._emit(decision, state) + return decision + # Estados transacionais preservam continuidade para respostas curtas # (parâmetros, "sim", "não"), mas NÃO podem aprisionar a sessão. Antes # de aplicar a política de estado, procuramos uma mudança explícita de @@ -79,18 +124,49 @@ class EnterpriseRouter: # pendente antes de executar a nova intent. state_decision = self._route_by_state(current_state) if state_decision: - consumed = await self._transaction_parameter_precedence( - state, text=str(text), state_decision=state_decision - ) - if consumed is not None: - await self._emit(consumed, state) - return consumed + tx_status = str(state.get("transaction_status") or "").strip().upper() + + # Confirmation is the only transaction input with absolute precedence: + # an explicit yes/no answers the confirmation contract itself. + if tx_status == "AWAITING_CONFIRMATION": + consumed = await self._transaction_parameter_precedence( + state, text=str(text), state_decision=state_decision + ) + if consumed is not None: + await self._emit(consumed, state) + return consumed + + # While collecting parameters, a turn may both contain a usable field + # value and express a new, incompatible goal. When semantic routing is + # available, classify CONTINUE vs SHIFT before extraction so a field + # value cannot shield a real intent change. Without semantic routing we + # preserve the previous conservative behavior (parameter first), because + # a broad configured keyword alone cannot reliably distinguish a new + # goal from a legitimate parameter utterance. + semantic_shift_available = bool(self.enable_llm_router and self.llm is not None) + if tx_status == "COLLECTING_PARAMETERS" and not semantic_shift_available: + consumed = await self._transaction_parameter_precedence( + state, text=str(text), state_decision=state_decision + ) + if consumed is not None: + await self._emit(consumed, state) + return consumed + interruption = await self._transaction_state_interruption_candidate( state, text=str(text), state_decision=state_decision ) if interruption is not None: await self._emit(interruption, state) return interruption + + if tx_status == "COLLECTING_PARAMETERS" and semantic_shift_available: + consumed = await self._transaction_parameter_precedence( + state, text=str(text), state_decision=state_decision + ) + if consumed is not None: + await self._emit(consumed, state) + return consumed + await self._emit(state_decision, state) return state_decision @@ -116,16 +192,30 @@ class EnterpriseRouter: method="state", next_state=tx_status, ) - consumed = await self._transaction_parameter_precedence( - state, text=str(text), state_decision=synthetic - ) - if consumed is not None: - consumed.metadata = { - **(consumed.metadata or {}), - "transaction_state_recovered": True, - } - await self._emit(consumed, state) - return consumed + if tx_status == "AWAITING_CONFIRMATION": + consumed = await self._transaction_parameter_precedence( + state, text=str(text), state_decision=synthetic + ) + if consumed is not None: + consumed.metadata = { + **(consumed.metadata or {}), + "transaction_state_recovered": True, + } + await self._emit(consumed, state) + return consumed + + semantic_shift_available = bool(self.enable_llm_router and self.llm is not None) + if tx_status == "COLLECTING_PARAMETERS" and not semantic_shift_available: + consumed = await self._transaction_parameter_precedence( + state, text=str(text), state_decision=synthetic + ) + if consumed is not None: + consumed.metadata = { + **(consumed.metadata or {}), + "transaction_state_recovered": True, + } + await self._emit(consumed, state) + return consumed interruption = await self._transaction_state_interruption_candidate( state, text=str(text), state_decision=synthetic @@ -138,6 +228,18 @@ class EnterpriseRouter: await self._emit(interruption, state) return interruption + if tx_status == "COLLECTING_PARAMETERS" and semantic_shift_available: + consumed = await self._transaction_parameter_precedence( + state, text=str(text), state_decision=synthetic + ) + if consumed is not None: + consumed.metadata = { + **(consumed.metadata or {}), + "transaction_state_recovered": True, + } + await self._emit(consumed, state) + return consumed + # A transação continua ativa e a mensagem NÃO representa mudança de # intenção. Neste caso a decisão sintética de estado precisa vencer # route stickiness/continuity. Antes, o código apenas verificava uma @@ -174,10 +276,17 @@ class EnterpriseRouter: await self._emit(keyword_candidate, state) return keyword_candidate - decision = await self.continuity.evaluate(state, intents=self.intents) - if decision: - await self._emit(decision, state) - return decision + # Uma transação terminal encerra também a elegibilidade de route + # stickiness/continuity herdada daquele fluxo no próximo roteamento. + # O histórico conversacional continua intacto, mas o agente/intenção + # anterior não pode capturar uma nova mensagem depois de COMPLETED, + # FAILED, CANCELLED, BLOCKED ou OUT_OF_SCOPE. Nesses casos a mensagem + # volta ao roteamento normal (keyword/LLM/fallback). + if not terminal_tx: + decision = await self.continuity.evaluate(state, intents=self.intents) + if decision: + await self._emit(decision, state) + return decision decision = self._route_by_keyword(text) if decision: @@ -211,11 +320,13 @@ class EnterpriseRouter: text: str, state_decision: RouteDecision, ) -> RouteDecision | None: - """Consume a turn as transaction parameters before evaluating intent shift. + """Consume a turn as transaction input after shift precedence is resolved. - Only COLLECTING_PARAMETERS participates. The LLM extracts values for the - currently missing parameters; if at least one value is found, the state - route wins deterministically and intent-shift classification is skipped. + AWAITING_CONFIRMATION consumes an explicit confirmation before any shift + classification. COLLECTING_PARAMETERS reaches this method only after the + router has established that the current turn does not represent an + incompatible intent-shift; then extracted values may continue the active + transaction deterministically. """ tx_status = str(state.get("transaction_status") or "").strip().upper() if tx_status == "AWAITING_CONFIRMATION": @@ -280,25 +391,33 @@ class EnterpriseRouter: previous = state.get("route_decision") or {} previous_intent = str(previous.get("intent") or state.get("intent") or started_intent).strip() - candidate = self._route_by_keyword(text) - if candidate is not None: + configured_candidate = self._route_by_keyword(text) + if configured_candidate is not None: different = ( - candidate.agent != state_decision.agent - or (started_intent and candidate.intent != started_intent) - or (previous_intent and not previous_intent.startswith("state:") and candidate.intent != previous_intent) + configured_candidate.agent != state_decision.agent + or (started_intent and configured_candidate.intent != started_intent) + or (previous_intent and not previous_intent.startswith("state:") and configured_candidate.intent != previous_intent) ) - if different: - candidate.metadata = { - **(candidate.metadata or {}), + if not different: + return None + + # During parameter collection, a configured keyword may be present in + # a perfectly valid parameter answer (for example an order identifier + # utterance containing the generic word "pedido"). When semantic + # classification is available, use the configured route only as a + # candidate hint and let the LLM decide CONTINUE vs SHIFT. This avoids + # both failure modes: parameter extraction cannot hide a real new goal, + # and a broad keyword cannot steal a legitimate parameter turn. + if not (self.enable_llm_router and self.llm is not None): + configured_candidate.metadata = { + **(configured_candidate.metadata or {}), "transaction_interruption": "intent_shift", "interrupted_state": state_decision.next_state, "interrupted_agent": state_decision.agent, "interrupted_intent": started_intent or previous_intent, "interruption_source": "configured_routing", } - return candidate - else: - return None + return configured_candidate if not (self.enable_llm_router and self.llm is not None): return None @@ -320,6 +439,15 @@ class EnterpriseRouter: "transaction_status": state.get("transaction_status"), "tool_name": active_tx.get("tool_name"), "missing_parameters": list(state.get("missing_parameters") or []), + "configured_candidate": ( + { + "intent": configured_candidate.intent, + "agent": configured_candidate.agent, + "confidence": configured_candidate.confidence, + } + if configured_candidate is not None + else None + ), } system = ( "Você decide apenas se o turno atual continua a transação ativa ou muda de intenção. " @@ -377,6 +505,9 @@ class EnterpriseRouter: "interrupted_agent": state_decision.agent, "interrupted_intent": started_intent or previous_intent, "interruption_source": "semantic_classifier", + "configured_routing_hint": ( + configured_candidate.intent if configured_candidate is not None else None + ), "raw_llm_answer": answer[:1000], }, domain=self._domain_for_intent(intent_name), diff --git a/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-313.pyc index 8c97908..7ec80b2 100644 Binary files a/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..6e59bce Binary files /dev/null and b/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc index 9d6a067..5ff8869 100644 Binary files a/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-314.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-314.pyc new file mode 100644 index 0000000..660e322 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_parameters.cpython-313.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_parameters.cpython-313.pyc new file mode 100644 index 0000000..2ae837f Binary files /dev/null and b/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_parameters.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_parameters.cpython-314.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_parameters.cpython-314.pyc new file mode 100644 index 0000000..ddee35a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_parameters.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py b/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py index f5aa1ef..837d048 100644 --- a/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py +++ b/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py @@ -11,6 +11,7 @@ from typing import Any, Iterable, Mapping from agent_framework.memory.summary_memory import MemoryContext, render_recent_messages from agent_framework.runtime.transaction_parameters import extract_transaction_parameters, parse_transaction_confirmation +from agent_framework.workflows.input_contract import match_expected_input logger = logging.getLogger(__name__) @@ -344,6 +345,23 @@ class AgentRuntimeMixin: deduped = list(dict.fromkeys(queries)) return required, "\n".join(deduped) + @classmethod + def _mcp_rag_sufficient(cls, mcp_results: list[dict[str, Any]]) -> bool: + """Retorna True somente quando o domínio declara que MCP basta para este turno. + + Um tool result bem-sucedido não é, por si só, evidência de suficiência + semântica. Para pular retrieval, a tool/workflow deve declarar + ``rag_sufficient=true`` ou ``knowledge_sufficient=true`` em seu payload. + Isso evita que o framework conheça nomes de tools ou termos de negócio. + """ + for item in mcp_results or []: + if not isinstance(item, dict) or not item.get("ok"): + continue + for mapping in cls._iter_mapping_values(item.get("result")): + if bool(mapping.get("rag_sufficient")) or bool(mapping.get("knowledge_sufficient")): + return True + return False + @classmethod def _mcp_llm_composition_directive(cls, mcp_results: list[dict[str, Any]]) -> tuple[bool, list[str]]: @@ -372,20 +390,31 @@ class AgentRuntimeMixin: async def _retrieve_rag_context(self, state: dict[str, Any]) -> tuple[str, dict[str, Any]]: rag_service = getattr(self, "rag_service", None) - if not rag_service: - return "", {"enabled": False} settings = getattr(self, "settings", None) + if not rag_service: + return "", { + "enabled": False, + "attempted": False, + "status": "no_service", + "reason": "rag_service_not_configured", + "provider": getattr(settings, "RAG_PROVIDER", "standard"), + } mcp_results = state.get("mcp_results") or [] requires_rag, rag_query_override = self._mcp_rag_directive(mcp_results) + explicit_mcp_sufficient = self._mcp_rag_sufficient(mcp_results) if ( not requires_rag and bool(getattr(settings, "SKIP_RAG_WHEN_MCP_SUFFICIENT", True)) - and any(r.get("ok") and r.get("result") for r in mcp_results) + and explicit_mcp_sufficient ): - text = str(state.get("sanitized_input") or state.get("user_text") or "").lower() - policy_terms = ("política", "politica", "regra", "prazo", "como funciona", "por que", "porque") - if not any(term in text for term in policy_terms): - return "", {"enabled": False, "skipped": True, "reason": "mcp_sufficient"} + return "", { + "enabled": False, + "skipped": True, + "reason": "mcp_explicitly_sufficient", + "required_by_tool": False, + "mcp_explicitly_sufficient": True, + "provider": getattr(settings, "RAG_PROVIDER", "standard"), + } runtime = self.get_runtime_context(state) namespace = ( (state.get("agent_profile") or {}).get("rag_namespace") @@ -411,10 +440,13 @@ class AgentRuntimeMixin: # observabilidade e para decisões posteriores. return "", { "enabled": False, + "attempted": True, "failed": True, "technical_error": True, "technical_error_in_rag": True, + "status": "error", "error": str(exc), + "provider": getattr(settings, "RAG_PROVIDER", "standard"), "namespace": namespace, "query": rag_query, "query_overridden_by_tool": bool(rag_query_override), @@ -442,24 +474,41 @@ class AgentRuntimeMixin: if any(not bool(getattr(d, "allowed", True)) for d in decisions): return "", { "enabled": False, + "attempted": True, "blocked": True, + "status": "blocked", "reason": "retrieval_guardrail", + "provider": result.metadata.get("provider") or getattr(settings, "RAG_PROVIDER", "standard"), + "namespace": namespace, + "query": rag_query, + "document_count": len(result.documents), "guardrails": retrieval_decisions, } context = guarded_context + document_count = len(result.documents) + provider = result.metadata.get("provider") or getattr(settings, "RAG_PROVIDER", "standard") + status = "executed" if context and document_count else "empty" return context, { "enabled": True, + "attempted": True, + "status": status, + "provider": provider, "namespace": namespace, "query": rag_query, "query_overridden_by_tool": bool(rag_query_override), "required_by_tool": bool(requires_rag), + "mcp_explicitly_sufficient": explicit_mcp_sufficient, "latency_ms": result.latency_ms, - "document_count": len(result.documents), + "document_count": document_count, "graph_neighbors": len(result.graph_neighbors), "top_document_ids": [d.id for d in result.documents[:5]], "top_scores": [d.score for d in result.documents[:5]], "rewritten": result.metadata.get("rewritten"), "effective_query": result.query, + "confidence": result.metadata.get("confidence"), + "low_confidence": result.metadata.get("low_confidence"), + "fallback_reason": result.metadata.get("fallback_reason"), + "warnings": result.metadata.get("warnings") or [], "guardrails": retrieval_decisions, } @@ -1241,13 +1290,58 @@ class AgentRuntimeMixin: return parse_transaction_confirmation(text) def _transaction_parameter_schema(self, tool_name: str, policy: dict[str, Any] | None = None) -> dict[str, Any]: - """Return generic schema metadata for transactional required parameters.""" + """Return schema metadata for transactional required parameters. + + Backward compatibility is intentional: + - legacy ``args_schema: {field: string}`` remains valid; + - enriched ``args_schema`` entries may provide ``type``/``description``; + - when a legacy entry has no description, a declarative description from + ``mcp_parameter_mapping.yaml`` is used when available. + + The framework never assigns domain meaning to a parameter name. It only + forwards metadata declared by the agent so the generic LLM extractor can + interpret the user's wording more accurately. + """ cfg = self._tool_config(tool_name) raw_schema = dict(getattr(cfg, "args_schema", {}) or {}) if cfg is not None else {} required = [str(name) for name in ((policy or {}).get("requires") or getattr(cfg, "requires", []) or [])] - if not required: - return raw_schema - return {name: raw_schema.get(name, "string") for name in required} + + # Optional semantic metadata already declared by the agent for MCP + # extraction. This is only a fallback; args_schema remains authoritative. + extract_rules: dict[str, dict[str, Any]] = {} + router = getattr(self, "tool_router", None) + if router is not None and hasattr(router, "parameter_extract_rules"): + try: + extract_rules = dict(router.parameter_extract_rules(tool_name) or {}) + except Exception: + # Schema construction must never break legacy agents merely + # because optional descriptive metadata cannot be loaded. + extract_rules = {} + + names = required or [str(name) for name in raw_schema.keys()] + normalized: dict[str, Any] = {} + for name in names: + raw = raw_schema.get(name, "string") + rule = extract_rules.get(name) if isinstance(extract_rules.get(name), dict) else {} + fallback_description = str((rule or {}).get("description") or "").strip() or None + + if isinstance(raw, dict): + entry = dict(raw) + entry.setdefault("type", "string") + if not entry.get("description") and fallback_description: + entry["description"] = fallback_description + normalized[name] = entry + elif fallback_description: + normalized[name] = { + "type": raw or "string", + "description": fallback_description, + } + else: + # Preserve the exact legacy representation when there is no + # additional metadata to contribute. + normalized[name] = raw or "string" + + return normalized def _transaction_tool_description(self, tool_name: str) -> str: cfg = self._tool_config(tool_name) @@ -1343,17 +1437,50 @@ class AgentRuntimeMixin: return f"WAITING_{self._agent_state_prefix(current)}_CONFIRMATION" @staticmethod - def _workflow_resume_decision(text: str) -> str: + def _workflow_resume_decision(text: str, pending: dict[str, Any] | None = None) -> str: + # Prefer the workflow's declarative input contract. This removes domain + # semantics from the framework: SIM/NAO, numeric choices or free text are + # interpreted only from ``expected_input`` persisted by the paused flow. + pause = (pending or {}).get("pause") if isinstance(pending, dict) else None + expected = pause.get("expected_input") if isinstance(pause, dict) else None + matched = match_expected_input(text, expected) + if matched is not None: + return matched + + # Backward compatibility for old checkpoints that predate expected_input. + # This branch is intentionally limited to the previous generic yes/no + # behavior and is not used when the workflow provides a contract. + if isinstance(expected, dict): + return "OUTRO" normalized = " ".join((text or "").strip().lower().split()) normalized = re.sub(r"[.!?]+$", "", normalized).strip() yes = {"sim", "s", "claro", "isso", "correto", "pode", "pode sim", "entendi", "conseguiu", "resolveu"} - no = {"não", "nao", "n", "não resolveu", "nao resolveu", "não entendi", "nao entendi", "não", "negativo"} + no = {"não", "nao", "n", "não resolveu", "nao resolveu", "não entendi", "nao entendi", "negativo"} if normalized in yes or normalized.startswith("sim "): return "SIM" if normalized in no or normalized.startswith("não ") or normalized.startswith("nao "): return "NAO" return "OUTRO" + @staticmethod + def _workflow_pause_descriptor(workflow: dict[str, Any]) -> dict[str, Any]: + """Recover the complete pause descriptor from a workflow result. + + Runtime v2 exposes ``pause`` as a compact public summary, while the + LangGraph interrupt carries ``expected_input`` and ``resume_from``. Keep + both forms compatible without coupling this logic to a domain workflow. + """ + descriptor = dict(workflow.get("pause") or {}) if isinstance(workflow.get("pause"), dict) else {} + state = workflow.get("state") if isinstance(workflow.get("state"), dict) else {} + interrupts = state.get("__interrupt__") if isinstance(state, dict) else None + if isinstance(interrupts, list) and interrupts: + first = interrupts[0] + value = first.get("value") if isinstance(first, dict) else None + if isinstance(value, dict): + for key, item in value.items(): + descriptor.setdefault(key, item) + return descriptor + @staticmethod def _workflow_payload_from_tool_result(result: dict[str, Any]) -> dict[str, Any] | None: data = result.get("result") if isinstance(result, dict) else None @@ -1379,12 +1506,26 @@ class AgentRuntimeMixin: executed.append(workflow_name) state["business_workflows_executed"] = executed if workflow.get("status") != "PAUSED": + # Clearing must be materialized in the graph-state patch. ``pop``/absence + # is not enough with LangGraph state merging: an older latch can survive + # into the next turn and incorrectly resume a workflow that already + # completed. Only clear the currently owned execution (or an unlabeled + # legacy latch); never clear a different concurrently tracked workflow. + pending = state.get("pending_domain_workflow") + pending_execution = (pending or {}).get("execution_id") if isinstance(pending, dict) else None + workflow_execution = metadata.get("workflow_execution_id") or workflow.get("execution_id") + if not pending_execution or not workflow_execution or str(pending_execution) == str(workflow_execution): + state["pending_domain_workflow"] = None + if state.get("transaction_status") == "WORKFLOW_PAUSED": + state["transaction_status"] = None return state["pending_domain_workflow"] = { "workflow_name": metadata.get("workflow_name") or workflow.get("workflow_name"), "execution_id": metadata.get("workflow_execution_id") or workflow.get("execution_id"), "resume_tool": metadata.get("resume_tool") or "retomar_workflow", - "pause": workflow.get("pause") or {}, + "owner_agent": state.get("active_agent") or state.get("route"), + "owner_intent": state.get("intent"), + "pause": self._workflow_pause_descriptor(workflow), } state["transaction_status"] = "WORKFLOW_PAUSED" @@ -1396,7 +1537,7 @@ class AgentRuntimeMixin: arguments = { "workflow_name": pending.get("workflow_name"), "execution_id": pending.get("execution_id"), - "resposta_usuario": self._workflow_resume_decision(text), + "resposta_usuario": self._workflow_resume_decision(text, pending), } result = await self._call_mcp_tool(tool_name, arguments, state) workflow = self._workflow_payload_from_tool_result(result) @@ -1404,7 +1545,10 @@ class AgentRuntimeMixin: if workflow and workflow.get("status") == "PAUSED": pass else: - state.pop("pending_domain_workflow", None) + # Explicit tombstone: transaction_state_patch() must carry the clear + # through LangGraph's state merge. Removing the key locally would let + # the previous PAUSED latch remain durable in the graph state. + state["pending_domain_workflow"] = None if state.get("transaction_status") == "WORKFLOW_PAUSED": state["transaction_status"] = None return result @@ -2000,11 +2144,19 @@ class AgentRuntimeMixin: return None def build_direct_mcp_answer(self, state: dict[str, Any], mcp_results: list[dict[str, Any]], *, agent_label: str) -> str | None: - """Resposta determinística para consultas estruturadas simples.""" + """Retorna resposta MCP direta somente quando a aplicação declarar isso explicitamente. + + Um resultado de tool não implica, por si só, que a pergunta do usuário foi + respondida. O core do framework não conhece nomes de tools nem formatos de + domínio. Para encerrar o fluxo antes de RAG/LLM, a configuração da tool deve + declarar ``response.direct: true`` e fornecer uma política de apresentação + válida. Sem essa declaração, o fluxo continua para retrieval/composição. + """ requires_rag, _ = self._mcp_rag_directive(mcp_results) requires_llm_composition, _ = self._mcp_llm_composition_directive(mcp_results) if requires_rag or requires_llm_composition: return None + ok = [r for r in mcp_results if r.get("ok") and isinstance(r.get("result"), dict)] for item in ok: workflow = self._workflow_payload_from_tool_result(item) @@ -2014,11 +2166,18 @@ class AgentRuntimeMixin: if prompt: return str(prompt) if workflow and workflow.get("status") == "COMPLETED": + # A completed workflow is not automatically a direct answer. Only + # the terminal node may provide an explicit message. Searching + # backwards for any prior ``mensagem`` can replay a prompt emitted + # before a pause (e.g. the question the user has just answered) and + # suppress the normal LLM/orchestrator composition of terminal data. nodes = workflow.get("output") if isinstance(workflow.get("output"), dict) else {} - # prefer last business message emitted by a workflow action - for value in reversed(list(nodes.values())): - if isinstance(value, dict) and str(value.get("mensagem") or "").strip(): - return str(value["mensagem"]).strip() + workflow_state = workflow.get("state") if isinstance(workflow.get("state"), dict) else {} + terminal_node = str(workflow_state.get("current_node") or "").strip() + terminal_output = nodes.get(terminal_node) if terminal_node else None + if isinstance(terminal_output, dict) and str(terminal_output.get("mensagem") or "").strip(): + return str(terminal_output["mensagem"]).strip() + text = state.get("sanitized_input") or state.get("user_text") or "" if ( len(ok) != 1 @@ -2026,30 +2185,79 @@ class AgentRuntimeMixin: or self._transactional_action_match(str(text)) is not None ): return None + tool = ok[0].get("tool_name") data = ok[0]["result"] + router = getattr(self, "tool_router", None) + registry = getattr(router, "registry", None) + cfg = registry.get_tool(str(tool)) if registry and tool else None + policy = dict(getattr(cfg, "response", None) or {}) if cfg else {} - # Primeiro tenta o contrato genérico e declarativo de apresentação. - # Se a aplicação não o configurou, preserva exatamente o fallback legado - # abaixo para não quebrar projetos existentes. - declared = self._render_declared_tool_response(tool, data, agent_label=agent_label, state=state) - if declared is not None: - return declared + # Importante: renderer/template descreve COMO apresentar uma resposta; + # somente ``direct: true`` declara que ela é semanticamente suficiente + # para encerrar o turno antes de RAG/LLM. + if not bool(policy.get("direct", False)): + return None - if tool == "consultar_pedido": - oid=data.get("order_id"); status=data.get("status"); total=data.get("valor_total") - lines=[f"[{agent_label}] Pedido {oid}: status {status}."] - if total is not None: lines.append(f"Valor total: R$ {float(total):.2f}.".replace('.', ',')) - items=data.get("itens") or [] - if items: lines.append("Itens: " + "; ".join(str(i.get("descricao") or i.get("nome") or i.get("sku")) for i in items) + ".") - return " ".join(lines) - if tool == "consultar_entrega": - return f"[{agent_label}] Entrega do pedido {data.get('order_id')}: transportadora {data.get('transportadora')}, rastreio {data.get('codigo_rastreio')}, previsão {data.get('previsao_entrega')}." - if tool == "consultar_plano": - return f"[{agent_label}] Seu plano é {data.get('plano')}, com {data.get('internet_gb')} GB e status {data.get('status')}." - if tool == "consultar_fatura": - return f"[{agent_label}] Fatura consultada: {data}." - return None + return self._render_declared_tool_response(tool, data, agent_label=agent_label, state=state) + + def _clear_active_interaction_context_on_route_shift(self, state: dict[str, Any]) -> bool: + """Invalidate active conversational latches when routing leaves their owner. + + This is deliberately generic. It compares the current route decision with + the owner recorded by a paused workflow; it does not inspect domain, tool, + workflow or intent names. Durable checkpoints/history remain intact. + """ + pending_workflow = state.get("pending_domain_workflow") + if not isinstance(pending_workflow, dict) or not pending_workflow.get("execution_id"): + return False + + route_decision = state.get("route_decision") if isinstance(state.get("route_decision"), dict) else {} + route_metadata = route_decision.get("metadata") if isinstance(route_decision.get("metadata"), dict) else {} + if route_metadata.get("workflow_resume"): + return False + + current_intent = str(route_decision.get("intent") or state.get("intent") or "").strip() + current_agent = str(route_decision.get("agent") or route_decision.get("route") or state.get("route") or "").strip() + owner_intent = str(pending_workflow.get("owner_intent") or "").strip() + owner_agent = str(pending_workflow.get("owner_agent") or "").strip() + + intent_changed = bool(owner_intent and current_intent and owner_intent != current_intent) + agent_changed = bool(owner_agent and current_agent and owner_agent != current_agent) + if not (intent_changed or agent_changed): + return False + + state["last_interrupted_domain_workflow"] = { + **pending_workflow, + "status": "CANCELLED", + "reason": "intent_shift", + } + state["pending_domain_workflow"] = None + + # The active interaction owns all operational latches, not the durable + # audit trail. Clear only live state so a new semantic route starts clean. + active_tx = self._active_transaction(state) + if isinstance(active_tx, dict) and active_tx.get("tool_name"): + self._finish_active_transaction(state, "CANCELLED") + else: + state["active_transaction"] = None + state["selected_tool_call"] = {} + state["pending_tool_call"] = {} + state["missing_parameters"] = [] + state["confirmation_required"] = False + state["confirmation_received"] = False + state["next_state"] = None + + if state.get("transaction_status") in {"WORKFLOW_PAUSED", "COLLECTING_PARAMETERS", "AWAITING_CONFIRMATION", "CANCELLED"}: + state["transaction_status"] = None + state["transaction_pre_validation"] = None + state["pending_tool_clarification"] = None + state["tool_policy_result"] = { + "action": "cleared_by_intent_shift", + "workflow_execution_id": pending_workflow.get("execution_id"), + } + state["mcp_results"] = [] + return True async def execute_tools_for_intent( self, @@ -2088,6 +2296,8 @@ class AgentRuntimeMixin: "tool_name": interrupted_tool, } + self._clear_active_interaction_context_on_route_shift(state) + # Clarificação de resultado de tool tem precedência: reutiliza a mesma tool # e argumentos, alterando apenas o parâmetro escolhido pelo usuário. if state.get("pending_tool_clarification"): @@ -2573,9 +2783,21 @@ class AgentRuntimeMixin: f"(persistidas pelo framework, não inferidas pela memória conversacional):\n{transaction_evidence}" ) if rag_context is not None: - sections.append(f"Contexto RAG nativo do framework:\n{rag_context or '[sem contexto RAG]'}") + sections.append(f"Contexto de conhecimento (RAG):\n{rag_context or '[sem contexto RAG]'}") if rag_metadata is not None: sections.append(f"Metadados RAG:\n{rag_metadata}") + provider = str(rag_metadata.get("provider") or getattr(getattr(self, "settings", None), "RAG_PROVIDER", "standard")) + grounded_only = bool(getattr(getattr(self, "settings", None), "RAG_GROUNDED_ONLY", False)) + if provider == "kbdb": + grounded_only = bool(getattr(getattr(self, "settings", None), "KBDB_GROUNDED_ONLY", True)) + if grounded_only: + sections.append( + "Política de grounding obrigatória:\n" + "- Use como fatos somente evidências presentes nos resultados MCP, no contexto RAG e no business context fornecido.\n" + "- Não complete lacunas usando conhecimento paramétrico do modelo, memória geral ou suposições.\n" + "- Se a informação pedida não estiver sustentada pelas evidências disponíveis, diga explicitamente que não há informação suficiente na base consultada.\n" + "- Se o RAG estiver vazio, bloqueado ou com erro, ainda é permitido responder apenas a partes comprovadas por MCP/business context; não invente a parte documental ausente." + ) for title, value in (extra_sections or {}).items(): sections.append(f"{title}:\n{value}") return MessageBuilder(state).system(system_prompt).user("\n\n".join(sections)).build() diff --git a/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py b/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py index b79bc08..475f077 100644 --- a/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py +++ b/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py @@ -114,9 +114,12 @@ async def extract_transaction_parameters( "3. Se nenhum parâmetro pendente foi realmente informado, devolva null para todos.\n" "4. Se houver apenas um parâmetro pendente, uma resposta contendo apenas um valor pode ser associada a ele quando isso for semanticamente inequívoco.\n" "5. Se houver vários parâmetros pendentes, extraia todos os que estiverem presentes no mesmo turno.\n" - "6. O nome do parâmetro não precisa aparecer literalmente na fala; use a semântica, o nome da transação e o schema para associar valores.\n" - "7. Em caso de dúvida, prefira null.\n" - "8. Responda SOMENTE JSON válido, sem markdown, sem explicação e sem chaves extras.\n\n" + "6. O nome do parâmetro não precisa aparecer literalmente na fala. Associe semanticamente o valor usando o nome da transação e os metadados disponíveis para cada campo.\n" + "7. Para cada parâmetro, considere o nome técnico, o tipo quando disponível e principalmente a descrição semântica quando disponível. A ausência de tipo ou descrição NÃO impede a extração.\n" + "8. Se a mensagem deixar clara a correspondência entre um trecho e um parâmetro, preencha-o mesmo que o usuário não cite o nome técnico do campo.\n" + "9. Não use conhecimento externo para completar valores ausentes e não transforme aproximações ou suposições em fatos.\n" + "10. Em caso de dúvida razoável sobre a correspondência ou o valor, prefira null.\n" + "11. Responda SOMENTE JSON válido, sem markdown, sem explicação e sem chaves extras.\n\n" f"transaction_tool: {tool_name}\n" f"transaction_description: {tool_description or ''}\n" f"pending_parameters: {json.dumps(pending, ensure_ascii=False)}\n" diff --git a/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc index b214a57..320825c 100644 Binary files a/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..9ac09c3 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc index 0fbc380..65b4de9 100644 Binary files a/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-314.pyc b/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-314.pyc new file mode 100644 index 0000000..b77449d Binary files /dev/null and b/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-313.pyc index 575e044..b6c01e7 100644 Binary files a/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..60c412d Binary files /dev/null and b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/supervisor/__pycache__/supervisor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/supervisor.cpython-313.pyc index c0e787c..5003257 100644 Binary files a/libs/agent_framework/src/agent_framework/supervisor/__pycache__/supervisor.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/supervisor.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/supervisor/__pycache__/supervisor.cpython-314.pyc b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/supervisor.cpython-314.pyc new file mode 100644 index 0000000..13df78c Binary files /dev/null and b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/supervisor.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-313.pyc index d95a6a7..8338651 100644 Binary files a/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-314.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..c074f71 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-313.pyc index b389a45..2ba5f61 100644 Binary files a/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-314.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-314.pyc new file mode 100644 index 0000000..075d8fe Binary files /dev/null and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/input_contract.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/input_contract.cpython-313.pyc new file mode 100644 index 0000000..c521ad1 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/input_contract.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-313.pyc index 15964e2..dba65ea 100644 Binary files a/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-314.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-314.pyc new file mode 100644 index 0000000..3b48e64 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-313.pyc index d9cddca..7c792a6 100644 Binary files a/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-314.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-314.pyc new file mode 100644 index 0000000..55efa0a Binary files /dev/null and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-313.pyc index 27e8cfa..277c35c 100644 Binary files a/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-314.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-314.pyc new file mode 100644 index 0000000..8179873 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-313.pyc index 5d38905..f695a2f 100644 Binary files a/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-314.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-314.pyc new file mode 100644 index 0000000..d9a32d4 Binary files /dev/null and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc index 0eddccb..5115c16 100644 Binary files a/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-314.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-314.pyc new file mode 100644 index 0000000..ef439eb Binary files /dev/null and b/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-314.pyc differ diff --git a/libs/agent_framework/src/agent_framework/workflows/input_contract.py b/libs/agent_framework/src/agent_framework/workflows/input_contract.py new file mode 100644 index 0000000..2492553 --- /dev/null +++ b/libs/agent_framework/src/agent_framework/workflows/input_contract.py @@ -0,0 +1,41 @@ +from __future__ import annotations + +from typing import Any + + +def normalize_expected_input(text: str, expected_input: dict[str, Any] | None) -> str: + """Normalize a workflow reply according to the declarative pause contract. + + The framework intentionally supports only explicit, deterministic normalizers. + Unknown normalizers fall back to ``strip`` instead of guessing semantics. + """ + rule = str((expected_input or {}).get("normalize") or "strip").strip().lower() + value = str(text or "") + if rule == "upper_strip": + return value.strip().upper() + if rule == "lower_strip": + return value.strip().lower() + return value.strip() + + +def match_expected_input(text: str, expected_input: dict[str, Any] | None) -> str | None: + """Return the normalized value only when it satisfies the workflow contract. + + With no ``allowed_values`` the normalized value is accepted when non-empty. + This keeps the capability generic for free-text pause contracts while making + enumerated contracts (SIM/NAO, choices, etc.) deterministic. + """ + if not isinstance(expected_input, dict): + return None + normalized = normalize_expected_input(text, expected_input) + if not normalized: + return None + allowed = expected_input.get("allowed_values") + if not allowed: + return normalized + allowed_normalized = { + normalize_expected_input(str(item), expected_input) + for item in allowed + if item is not None + } + return normalized if normalized in allowed_normalized else None diff --git a/mcp/servers/retail_mcp_server/__pycache__/main.cpython-314.pyc b/mcp/servers/retail_mcp_server/__pycache__/main.cpython-314.pyc new file mode 100644 index 0000000..300cc32 Binary files /dev/null and b/mcp/servers/retail_mcp_server/__pycache__/main.cpython-314.pyc differ diff --git a/mcp/servers/telecom_mcp_server/__pycache__/main.cpython-314.pyc b/mcp/servers/telecom_mcp_server/__pycache__/main.cpython-314.pyc new file mode 100644 index 0000000..f870717 Binary files /dev/null and b/mcp/servers/telecom_mcp_server/__pycache__/main.cpython-314.pyc differ diff --git a/templates/agent_template_backend/.env.example b/templates/agent_template_backend/.env.example index 116eb7d..16527cf 100644 --- a/templates/agent_template_backend/.env.example +++ b/templates/agent_template_backend/.env.example @@ -207,3 +207,30 @@ LONG_TERM_MEMORY_MAX_CONTEXT_ITEMS=20 LONG_TERM_MEMORY_MIN_CONFIDENCE=0.70 LONG_TERM_MEMORY_AUTO_EXTRACT=true LONG_TERM_MEMORY_INJECT_CONTEXT=true + +############################################################################### +# RAG provider selection (mutually exclusive at runtime) +############################################################################### +# standard = RAG original do agent_framework_oci (default, backward compatible) +# kbdb = KBDB enterprise via PKG_KB_SERVING.SEARCH_KNOWLEDGE_BASE +RAG_PROVIDER=standard + +# Somente usados quando RAG_PROVIDER=kbdb. KBDB pode estar em outro Autonomous; +# não há fallback para ADB_*. KBDB_DB_DSN deve ser alias TNS da wallet KBDB. +KBDB_DB_USER= +KBDB_DB_PASSWORD= +KBDB_DB_DSN= +KBDB_DB_WALLET_LOCATION= +KBDB_DB_WALLET_PASSWORD= +KBDB_SEARCH_TYPE=hybrid +KBDB_NODE_EXPANSION=true +KBDB_NODE_MAX_RELATED=8 +KBDB_GRAPH_CROSS_REF=false +KBDB_MAX_CROSS_REF_HOPS=1 +KBDB_DOCUMENT_TYPE=customer_safe +KBDB_METADATA_JSON= +KBDB_MIN_SCORE= + +# RAG grounding +RAG_GROUNDED_ONLY=false +KBDB_GROUNDED_ONLY=true diff --git a/templates/agent_template_backend/app/__pycache__/__init__.cpython-314.pyc b/templates/agent_template_backend/app/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..4f34490 Binary files /dev/null and b/templates/agent_template_backend/app/__pycache__/__init__.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/__pycache__/main.cpython-314.pyc b/templates/agent_template_backend/app/__pycache__/main.cpython-314.pyc new file mode 100644 index 0000000..15378ed Binary files /dev/null and b/templates/agent_template_backend/app/__pycache__/main.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/__pycache__/state.cpython-314.pyc b/templates/agent_template_backend/app/__pycache__/state.cpython-314.pyc new file mode 100644 index 0000000..642a1e4 Binary files /dev/null and b/templates/agent_template_backend/app/__pycache__/state.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/agents/__pycache__/billing_agent.cpython-314.pyc b/templates/agent_template_backend/app/agents/__pycache__/billing_agent.cpython-314.pyc new file mode 100644 index 0000000..12a8696 Binary files /dev/null and b/templates/agent_template_backend/app/agents/__pycache__/billing_agent.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/agents/__pycache__/orders_agent.cpython-314.pyc b/templates/agent_template_backend/app/agents/__pycache__/orders_agent.cpython-314.pyc new file mode 100644 index 0000000..383d963 Binary files /dev/null and b/templates/agent_template_backend/app/agents/__pycache__/orders_agent.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/agents/__pycache__/product_agent.cpython-314.pyc b/templates/agent_template_backend/app/agents/__pycache__/product_agent.cpython-314.pyc new file mode 100644 index 0000000..0f0b10e Binary files /dev/null and b/templates/agent_template_backend/app/agents/__pycache__/product_agent.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/agents/__pycache__/prompting.cpython-314.pyc b/templates/agent_template_backend/app/agents/__pycache__/prompting.cpython-314.pyc new file mode 100644 index 0000000..df4ccb9 Binary files /dev/null and b/templates/agent_template_backend/app/agents/__pycache__/prompting.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/agents/__pycache__/runtime.cpython-314.pyc b/templates/agent_template_backend/app/agents/__pycache__/runtime.cpython-314.pyc new file mode 100644 index 0000000..9545b88 Binary files /dev/null and b/templates/agent_template_backend/app/agents/__pycache__/runtime.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/agents/__pycache__/support_agent.cpython-314.pyc b/templates/agent_template_backend/app/agents/__pycache__/support_agent.cpython-314.pyc new file mode 100644 index 0000000..54dbc3d Binary files /dev/null and b/templates/agent_template_backend/app/agents/__pycache__/support_agent.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/agents/product_agent.py b/templates/agent_template_backend/app/agents/product_agent.py index 34433f5..113bd8e 100644 --- a/templates/agent_template_backend/app/agents/product_agent.py +++ b/templates/agent_template_backend/app/agents/product_agent.py @@ -75,15 +75,30 @@ class ProductAgent(AgentRuntimeMixin): } rag_context, rag_metadata = await self._retrieve_rag_context(state) - if rag_metadata.get("enabled"): + rag_event_payload = { + "provider": rag_metadata.get("provider"), + "status": rag_metadata.get("status"), + "attempted": rag_metadata.get("attempted"), + "enabled": rag_metadata.get("enabled"), + "document_count": rag_metadata.get("document_count"), + "graph_neighbors": rag_metadata.get("graph_neighbors"), + "latency_ms": rag_metadata.get("latency_ms"), + "reason": rag_metadata.get("reason"), + "error": rag_metadata.get("error"), + "query": rag_metadata.get("query"), + "namespace": rag_metadata.get("namespace"), + } + await self._emit_ic( + "IC.PRODUCT_RAG_CONTEXT_EVALUATED", + state, + rag_event_payload, + component="agent.product.rag", + ) + if rag_metadata.get("enabled") and rag_metadata.get("status") == "executed": await self._emit_ic( "IC.PRODUCT_RAG_CONTEXT_RETRIEVED", state, - { - "document_count": rag_metadata.get("document_count"), - "graph_neighbors": rag_metadata.get("graph_neighbors"), - "latency_ms": rag_metadata.get("latency_ms"), - }, + rag_event_payload, component="agent.product.rag", ) diff --git a/templates/agent_template_backend/app/observability/__pycache__/__init__.cpython-314.pyc b/templates/agent_template_backend/app/observability/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..021ac35 Binary files /dev/null and b/templates/agent_template_backend/app/observability/__pycache__/__init__.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/observability/__pycache__/telemetry_observer.cpython-314.pyc b/templates/agent_template_backend/app/observability/__pycache__/telemetry_observer.cpython-314.pyc new file mode 100644 index 0000000..78794e7 Binary files /dev/null and b/templates/agent_template_backend/app/observability/__pycache__/telemetry_observer.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/presentation/__pycache__/__init__.cpython-314.pyc b/templates/agent_template_backend/app/presentation/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..128f753 Binary files /dev/null and b/templates/agent_template_backend/app/presentation/__pycache__/__init__.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/presentation/__pycache__/tool_renderers.cpython-314.pyc b/templates/agent_template_backend/app/presentation/__pycache__/tool_renderers.cpython-314.pyc new file mode 100644 index 0000000..6045cee Binary files /dev/null and b/templates/agent_template_backend/app/presentation/__pycache__/tool_renderers.cpython-314.pyc differ diff --git a/templates/agent_template_backend/app/workflows/__pycache__/agent_graph.cpython-314.pyc b/templates/agent_template_backend/app/workflows/__pycache__/agent_graph.cpython-314.pyc new file mode 100644 index 0000000..7e6e5fc Binary files /dev/null and b/templates/agent_template_backend/app/workflows/__pycache__/agent_graph.cpython-314.pyc differ diff --git a/templates/agent_template_backend/data/agent_framework.db b/templates/agent_template_backend/data/agent_framework.db deleted file mode 100644 index ddf1883..0000000 Binary files a/templates/agent_template_backend/data/agent_framework.db and /dev/null differ diff --git a/templates/agent_template_backend_day_zero/.env.example b/templates/agent_template_backend_day_zero/.env.example index 116eb7d..eeb7130 100644 --- a/templates/agent_template_backend_day_zero/.env.example +++ b/templates/agent_template_backend_day_zero/.env.example @@ -207,3 +207,25 @@ LONG_TERM_MEMORY_MAX_CONTEXT_ITEMS=20 LONG_TERM_MEMORY_MIN_CONFIDENCE=0.70 LONG_TERM_MEMORY_AUTO_EXTRACT=true LONG_TERM_MEMORY_INJECT_CONTEXT=true + +############################################################################### +# RAG provider selection (mutually exclusive at runtime) +############################################################################### +# standard = RAG original do agent_framework_oci (default, backward compatible) +# kbdb = KBDB enterprise via PKG_KB_SERVING.SEARCH_KNOWLEDGE_BASE +RAG_PROVIDER=standard + +# Somente usados quando RAG_PROVIDER=kbdb. Se vazios, credenciais caem para ADB_*. +KBDB_DB_USER= +KBDB_DB_PASSWORD= +KBDB_DB_DSN= +KBDB_DB_WALLET_LOCATION= +KBDB_DB_WALLET_PASSWORD= +KBDB_SEARCH_TYPE=hybrid +KBDB_NODE_EXPANSION=true +KBDB_NODE_MAX_RELATED=8 +KBDB_GRAPH_CROSS_REF=false +KBDB_MAX_CROSS_REF_HOPS=1 +KBDB_DOCUMENT_TYPE=customer_safe +KBDB_METADATA_JSON= +KBDB_MIN_SCORE= diff --git a/templates/agent_template_backend_day_zero/data/agent_framework.db b/templates/agent_template_backend_day_zero/data/agent_framework.db deleted file mode 100644 index d1d18fd..0000000 Binary files a/templates/agent_template_backend_day_zero/data/agent_framework.db and /dev/null differ diff --git a/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc index 6ffeb33..b45edff 100644 Binary files a/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc and b/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_generic_tool_response_presentation.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/test_generic_tool_response_presentation.cpython-313-pytest-9.0.2.pyc index fccf00c..e2a7c21 100644 Binary files a/tests/__pycache__/test_generic_tool_response_presentation.cpython-313-pytest-9.0.2.pyc and b/tests/__pycache__/test_generic_tool_response_presentation.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_mcp_parameter_extraction_runtime.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/test_mcp_parameter_extraction_runtime.cpython-313-pytest-9.0.2.pyc index 2c07d30..391c614 100644 Binary files a/tests/__pycache__/test_mcp_parameter_extraction_runtime.cpython-313-pytest-9.0.2.pyc and b/tests/__pycache__/test_mcp_parameter_extraction_runtime.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_paused_workflow_resume_precedence.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/test_paused_workflow_resume_precedence.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000..4ef41f5 Binary files /dev/null and b/tests/__pycache__/test_paused_workflow_resume_precedence.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_performance_optimizations.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/test_performance_optimizations.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000..dafcf30 Binary files /dev/null and b/tests/__pycache__/test_performance_optimizations.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_route_stickiness_transaction_shift.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/test_route_stickiness_transaction_shift.cpython-313-pytest-9.0.2.pyc index 3bb1c66..86b3d26 100644 Binary files a/tests/__pycache__/test_route_stickiness_transaction_shift.cpython-313-pytest-9.0.2.pyc and b/tests/__pycache__/test_route_stickiness_transaction_shift.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_transaction_parameter_descriptions.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/test_transaction_parameter_descriptions.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000..6fdde9d Binary files /dev/null and b/tests/__pycache__/test_transaction_parameter_descriptions.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_transaction_parameter_llm_precedence.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/test_transaction_parameter_llm_precedence.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000..9d8ca51 Binary files /dev/null and b/tests/__pycache__/test_transaction_parameter_llm_precedence.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_transaction_state_regression_matrix.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/test_transaction_state_regression_matrix.cpython-313-pytest-9.0.2.pyc index dd780db..e1bc6e7 100644 Binary files a/tests/__pycache__/test_transaction_state_regression_matrix.cpython-313-pytest-9.0.2.pyc and b/tests/__pycache__/test_transaction_state_regression_matrix.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_transactional_tool_flow.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/test_transactional_tool_flow.cpython-313-pytest-9.0.2.pyc index 2abadb1..9756659 100644 Binary files a/tests/__pycache__/test_transactional_tool_flow.cpython-313-pytest-9.0.2.pyc and b/tests/__pycache__/test_transactional_tool_flow.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/test_generic_tool_response_presentation.py b/tests/test_generic_tool_response_presentation.py index f57feaa..eb54c61 100644 --- a/tests/test_generic_tool_response_presentation.py +++ b/tests/test_generic_tool_response_presentation.py @@ -43,7 +43,7 @@ def test_renderer_mode_uses_application_registered_renderer(): return f"[{agent_label}] {result['name']} / {state['intent']}" register_tool_response_renderer("test.entity", renderer) - rt = _Runtime({"consultar_algo": {"mode": "renderer", "renderer": "test.entity"}}) + rt = _Runtime({"consultar_algo": {"mode": "renderer", "renderer": "test.entity", "direct": True}}) answer = rt.build_direct_mcp_answer( {"user_text": "consulta", "intent": "test_intent"}, _result("consultar_algo", {"name": "OK"}), @@ -52,21 +52,74 @@ def test_renderer_mode_uses_application_registered_renderer(): assert answer == "[TestAgent] OK / test_intent" -def test_missing_renderer_falls_back_without_breaking_runtime(): - rt = _Runtime({"consultar_plano": {"mode": "renderer", "renderer": "missing.renderer"}}) +def test_missing_renderer_does_not_break_runtime_or_use_domain_fallback(): + rt = _Runtime({"consultar_plano": {"mode": "renderer", "renderer": "missing.renderer", "direct": True}}) answer = rt.build_direct_mcp_answer( {"user_text": "qual meu plano"}, _result("consultar_plano", {"plano": "Controle", "internet_gb": 50, "status": "ATIVO"}), agent_label="ProductAgent", ) - assert answer == "[ProductAgent] Seu plano é Controle, com 50 GB e status ATIVO." + assert answer is None -def test_no_declared_response_keeps_legacy_fallback(): +def test_renderer_without_explicit_direct_continues_to_llm_or_rag(): + def renderer(*, tool_name, result, state, agent_label): + return f"[{agent_label}] {result['plano']}" + + register_tool_response_renderer("test.plan", renderer) + rt = _Runtime({"consultar_plano": {"mode": "renderer", "renderer": "test.plan"}}) + answer = rt.build_direct_mcp_answer( + {"user_text": "como funciona a tarifação do plano?"}, + _result("consultar_plano", {"plano": "Controle", "internet_gb": 50, "status": "ATIVO"}), + agent_label="ProductAgent", + ) + assert answer is None + + +def test_no_declared_response_has_no_domain_hardcoded_fallback(): rt = _Runtime({}) answer = rt.build_direct_mcp_answer( {"user_text": "qual meu plano"}, _result("consultar_plano", {"plano": "Controle", "internet_gb": 50, "status": "ATIVO"}), agent_label="ProductAgent", ) - assert answer == "[ProductAgent] Seu plano é Controle, com 50 GB e status ATIVO." + assert answer is None + + +def test_completed_workflow_does_not_replay_message_from_non_terminal_node(): + rt = AgentRuntimeMixin() + state = {"user_text": "nao", "sanitized_input": "nao"} + result = { + "ok": True, + "tool_name": "resume_workflow", + "result": { + "status": "COMPLETED", + "workflow_name": "example", + "output": { + "format": {"mensagem": "Pergunta antiga?"}, + "decide": {"ok": True}, + "check": {"has_items": True}, + }, + "state": {"current_node": "check"}, + }, + } + assert rt.build_direct_mcp_answer(state, [result], agent_label="Agent") is None + + +def test_completed_workflow_uses_only_terminal_node_explicit_message(): + rt = AgentRuntimeMixin() + state = {"user_text": "ok", "sanitized_input": "ok"} + result = { + "ok": True, + "tool_name": "resume_workflow", + "result": { + "status": "COMPLETED", + "workflow_name": "example", + "output": { + "format": {"mensagem": "Pergunta antiga?"}, + "finish": {"mensagem": "Resposta final."}, + }, + "state": {"current_node": "finish"}, + }, + } + assert rt.build_direct_mcp_answer(state, [result], agent_label="Agent") == "Resposta final." diff --git a/tests/test_paused_workflow_resume_precedence.py b/tests/test_paused_workflow_resume_precedence.py new file mode 100644 index 0000000..2772a8d --- /dev/null +++ b/tests/test_paused_workflow_resume_precedence.py @@ -0,0 +1,336 @@ +from types import SimpleNamespace + +import pytest + +from agent_framework.routing.enterprise_router import EnterpriseRouter +from agent_framework.runtime.agent_runtime import AgentRuntimeMixin +from agent_framework.workflows.input_contract import match_expected_input + + +ROUTING_YAML = """ +router: + fallback_agent: billing_agent + confidence_threshold: 0.70 +intents: + - name: billing_invoice_explanation + domain: telecom + agent: faturas_agent + priority: 40 + keywords: [fatura] +""" + + +class _ContinuityLLM: + async def ainvoke(self, messages, **kwargs): + if kwargs.get("profile_name") == "route_continuity": + return '{"decision":"END_SESSION","confidence":0.99,"reason":"sim"}' + return '{}' + + +def _router(tmp_path): + routing = tmp_path / "routing.yaml" + routing.write_text(ROUTING_YAML, encoding="utf-8") + settings = SimpleNamespace( + ROUTING_CONFIG_PATH=str(routing), + ENABLE_LLM_ROUTER=False, + ENABLE_ROUTE_STICKINESS=True, + ROUTE_STICKINESS_LLM_PROFILE="route_continuity", + ROUTE_STICKINESS_CONFIDENCE_THRESHOLD=0.7, + ) + return EnterpriseRouter(settings, llm=_ContinuityLLM()) + + +def _workflow_result(): + return { + "result": { + "result": { + "status": "PAUSED", + "execution_id": "exec-1", + "workflow_name": "invoice_explanation", + "metadata": { + "workflow_name": "invoice_explanation", + "workflow_execution_id": "exec-1", + "resume_tool": "retomar_workflow", + }, + "pause": {"node": "formatar"}, + "state": { + "__interrupt__": [ + { + "value": { + "node": "formatar", + "prompt": "Sanei sua dúvida?", + "expected_input": { + "key": "resposta_usuario", + "allowed_values": ["SIM", "NAO"], + "normalize": "upper_strip", + }, + "resume_from": "decisao", + }, + "id": "interrupt-1", + } + ] + }, + } + } + } + + +class _Runtime(AgentRuntimeMixin): + async def _call_mcp_tool(self, tool_name, arguments, state): + self.called = (tool_name, arguments) + return { + "result": { + "result": { + "status": "COMPLETED", + "execution_id": arguments["execution_id"], + "workflow_name": arguments["workflow_name"], + "metadata": {"workflow_name": arguments["workflow_name"]}, + } + } + } + + +def test_capture_recovers_expected_input_from_interrupt_descriptor(): + runtime = _Runtime() + state = {"route": "faturas_agent", "active_agent": "faturas_agent", "intent": "billing_invoice_explanation"} + runtime._capture_pending_domain_workflow(state, _workflow_result()) + pending = state["pending_domain_workflow"] + assert pending["owner_agent"] == "faturas_agent" + assert pending["pause"]["expected_input"]["allowed_values"] == ["SIM", "NAO"] + assert pending["pause"]["resume_from"] == "decisao" + + +def test_expected_input_contract_is_deterministic(): + contract = {"allowed_values": ["SIM", "NAO"], "normalize": "upper_strip"} + assert match_expected_input(" sim ", contract) == "SIM" + assert match_expected_input("não", contract) is None + assert match_expected_input("quero minha fatura", contract) is None + + +@pytest.mark.asyncio +async def test_paused_workflow_expected_input_preempts_route_continuity(tmp_path): + router = _router(tmp_path) + state = { + "user_text": "sim", + "sanitized_input": "sim", + "route": "faturas_agent", + "active_agent": "faturas_agent", + "intent": "billing_invoice_explanation", + "route_decision": { + "route": "faturas_agent", + "agent": "faturas_agent", + "intent": "billing_invoice_explanation", + "domain": "telecom", + }, + "pending_domain_workflow": { + "workflow_name": "invoice_explanation", + "execution_id": "exec-1", + "resume_tool": "retomar_workflow", + "owner_agent": "faturas_agent", + "owner_intent": "billing_invoice_explanation", + "pause": { + "expected_input": { + "key": "resposta_usuario", + "allowed_values": ["SIM", "NAO"], + "normalize": "upper_strip", + } + }, + }, + } + decision = await router.route(state) + assert decision.method == "state" + assert decision.metadata["workflow_resume"] is True + assert decision.route == "faturas_agent" + assert decision.mcp_tools == ["retomar_workflow"] + assert decision.metadata["normalized_input"] == "SIM" + + +@pytest.mark.asyncio +async def test_runtime_resume_uses_contract_normalized_value(): + runtime = _Runtime() + state = { + "pending_domain_workflow": { + "workflow_name": "invoice_explanation", + "execution_id": "exec-1", + "resume_tool": "retomar_workflow", + "pause": { + "expected_input": { + "key": "resposta_usuario", + "allowed_values": ["SIM", "NAO"], + "normalize": "upper_strip", + } + }, + }, + "transaction_status": "WORKFLOW_PAUSED", + } + result = await runtime._resume_pending_domain_workflow(state, " sim ") + assert result is not None + assert runtime.called[0] == "retomar_workflow" + assert runtime.called[1]["resposta_usuario"] == "SIM" + assert state["pending_domain_workflow"] is None + + +def test_terminal_workflow_capture_materializes_latch_clear_for_graph_merge(): + runtime = _Runtime() + state = { + "pending_domain_workflow": { + "workflow_name": "invoice_explanation", + "execution_id": "exec-1", + "resume_tool": "retomar_workflow", + }, + "transaction_status": "WORKFLOW_PAUSED", + } + runtime._capture_pending_domain_workflow( + state, + { + "result": { + "result": { + "status": "COMPLETED", + "execution_id": "exec-1", + "workflow_name": "invoice_explanation", + "metadata": { + "workflow_name": "invoice_explanation", + "workflow_execution_id": "exec-1", + }, + } + } + }, + ) + assert state["pending_domain_workflow"] is None + assert state["transaction_status"] is None + patch = runtime.transaction_state_patch(state) + assert "pending_domain_workflow" in patch + assert patch["pending_domain_workflow"] is None + + +def test_terminal_workflow_does_not_clear_different_pending_execution(): + runtime = _Runtime() + pending = { + "workflow_name": "other_workflow", + "execution_id": "exec-other", + "resume_tool": "retomar_workflow", + } + state = {"pending_domain_workflow": dict(pending), "transaction_status": "WORKFLOW_PAUSED"} + runtime._capture_pending_domain_workflow( + state, + { + "result": { + "result": { + "status": "COMPLETED", + "execution_id": "exec-1", + "workflow_name": "invoice_explanation", + "metadata": { + "workflow_name": "invoice_explanation", + "workflow_execution_id": "exec-1", + }, + } + } + }, + ) + assert state["pending_domain_workflow"] == pending + assert state["transaction_status"] == "WORKFLOW_PAUSED" + + +def test_route_shift_clears_paused_workflow_and_live_latches_without_touching_history(): + runtime = _Runtime() + state = { + "route": "new_agent", + "intent": "new_intent", + "route_decision": { + "route": "new_agent", + "agent": "new_agent", + "intent": "new_intent", + "metadata": {}, + }, + "pending_domain_workflow": { + "workflow_name": "old_workflow", + "execution_id": "exec-old", + "resume_tool": "resume_old", + "owner_agent": "old_agent", + "owner_intent": "old_intent", + "pause": {"expected_input": {"allowed_values": ["YES", "NO"]}}, + }, + "transaction_status": "WORKFLOW_PAUSED", + "selected_tool_call": {"tool_name": "old_tool", "arguments": {"x": 1}}, + "pending_tool_call": {"tool_name": "old_tool", "arguments": {"x": 1}}, + "missing_parameters": ["x"], + "confirmation_required": True, + "confirmation_received": True, + "next_state": "OLD_STATE", + "transaction_pre_validation": {"eligible": True}, + "pending_tool_clarification": {"tool_name": "old_tool"}, + "mcp_results": [{"tool_name": "resume_old", "ok": False}], + "business_workflows_executed": ["historical_workflow"], + } + + changed = runtime._clear_active_interaction_context_on_route_shift(state) + + assert changed is True + assert state["pending_domain_workflow"] is None + assert state["transaction_status"] is None + assert state["selected_tool_call"] == {} + assert state["pending_tool_call"] == {} + assert state["missing_parameters"] == [] + assert state["confirmation_required"] is False + assert state["confirmation_received"] is False + assert state["next_state"] is None + assert state["transaction_pre_validation"] is None + assert state["pending_tool_clarification"] is None + assert state["mcp_results"] == [] + assert state["business_workflows_executed"] == ["historical_workflow"] + assert state["last_interrupted_domain_workflow"]["execution_id"] == "exec-old" + assert state["last_interrupted_domain_workflow"]["reason"] == "intent_shift" + + +def test_workflow_resume_does_not_clear_paused_workflow(): + runtime = _Runtime() + pending = { + "workflow_name": "wf", + "execution_id": "exec-1", + "owner_agent": "agent-a", + "owner_intent": "intent-a", + } + state = { + "route": "agent-a", + "intent": "intent-a", + "route_decision": { + "route": "agent-a", + "agent": "agent-a", + "intent": "intent-a", + "metadata": {"workflow_resume": True}, + }, + "pending_domain_workflow": dict(pending), + "transaction_status": "WORKFLOW_PAUSED", + "mcp_results": [{"tool_name": "something"}], + } + + changed = runtime._clear_active_interaction_context_on_route_shift(state) + + assert changed is False + assert state["pending_domain_workflow"] == pending + assert state["transaction_status"] == "WORKFLOW_PAUSED" + assert state["mcp_results"] == [{"tool_name": "something"}] + + +def test_same_workflow_owner_without_resume_does_not_get_cleared_as_intent_shift(): + runtime = _Runtime() + pending = { + "workflow_name": "wf", + "execution_id": "exec-1", + "owner_agent": "agent-a", + "owner_intent": "intent-a", + } + state = { + "route": "agent-a", + "intent": "intent-a", + "route_decision": { + "route": "agent-a", + "agent": "agent-a", + "intent": "intent-a", + "metadata": {}, + }, + "pending_domain_workflow": dict(pending), + "transaction_status": "WORKFLOW_PAUSED", + } + assert runtime._clear_active_interaction_context_on_route_shift(state) is False + assert state["pending_domain_workflow"] == pending diff --git a/tests/test_transaction_parameter_descriptions.py b/tests/test_transaction_parameter_descriptions.py new file mode 100644 index 0000000..8dab5db --- /dev/null +++ b/tests/test_transaction_parameter_descriptions.py @@ -0,0 +1,122 @@ +from __future__ import annotations + +import json +from types import SimpleNamespace + +import pytest + +from agent_framework.runtime.agent_runtime import AgentRuntimeMixin +from agent_framework.runtime.transaction_parameters import extract_transaction_parameters + + +class _Router: + def __init__(self, tool, rules=None): + self.registry = SimpleNamespace(get_tool=lambda name: tool if name == "tx_tool" else None) + self._rules = rules or {} + + def parameter_extract_rules(self, tool_name): + return dict(self._rules) + + +class _Runtime(AgentRuntimeMixin): + def __init__(self, tool, rules=None): + self.tool_router = _Router(tool, rules) + + +class _CaptureLLM: + def __init__(self): + self.prompt = "" + + async def ainvoke(self, messages, **kwargs): + self.prompt = messages[-1]["content"] + return json.dumps({"subject": "TIM CTRL Redes Sociais 8.0", "valor": None}, ensure_ascii=False) + + +def test_legacy_args_schema_remains_unchanged_without_description(): + tool = SimpleNamespace(args_schema={"subject": "string", "valor": "number"}, requires=["subject", "valor"]) + runtime = _Runtime(tool) + + schema = runtime._transaction_parameter_schema("tx_tool", {"requires": ["subject", "valor"]}) + + assert schema == {"subject": "string", "valor": "number"} + + +def test_legacy_args_schema_is_enriched_from_mcp_mapping_description(): + tool = SimpleNamespace(args_schema={"subject": "string", "valor": "number"}, requires=["subject", "valor"]) + runtime = _Runtime( + tool, + { + "subject": { + "from": "message", + "strategy": "llm", + "description": "Nome do serviço, produto, item ou cobrança objeto da contestação.", + }, + "valor": { + "from": "message", + "strategy": "llm", + "description": "Valor monetário explicitamente informado pelo cliente.", + }, + }, + ) + + schema = runtime._transaction_parameter_schema("tx_tool", {"requires": ["subject", "valor"]}) + + assert schema["subject"] == { + "type": "string", + "description": "Nome do serviço, produto, item ou cobrança objeto da contestação.", + } + assert schema["valor"] == { + "type": "number", + "description": "Valor monetário explicitamente informado pelo cliente.", + } + + +def test_enriched_args_schema_has_precedence_over_mcp_mapping_description(): + tool = SimpleNamespace( + args_schema={ + "subject": {"type": "string", "description": "Descrição definida no args_schema."}, + "valor": {"type": "number"}, + }, + requires=["subject", "valor"], + ) + runtime = _Runtime( + tool, + { + "subject": {"description": "Fallback que não deve sobrescrever."}, + "valor": {"description": "Descrição de fallback para valor."}, + }, + ) + + schema = runtime._transaction_parameter_schema("tx_tool", {"requires": ["subject", "valor"]}) + + assert schema["subject"]["description"] == "Descrição definida no args_schema." + assert schema["valor"] == {"type": "number", "description": "Descrição de fallback para valor."} + + +@pytest.mark.asyncio +async def test_extractor_prompt_uses_optional_semantic_descriptions_and_keeps_null_rule(): + llm = _CaptureLLM() + extracted = await extract_transaction_parameters( + llm, + text="nao contratei TIM CTRL Redes Sociais 8.0", + tool_name="contestar_cobranca", + missing_parameters=["subject", "valor"], + known_arguments={}, + parameter_schema={ + "subject": { + "type": "string", + "description": "Nome do serviço, produto, item ou cobrança objeto da contestação.", + }, + "valor": { + "type": "number", + "description": "Valor monetário explicitamente informado pelo cliente.", + }, + }, + tool_description="Executa contestação de cobrança.", + ) + + assert extracted == {"subject": "TIM CTRL Redes Sociais 8.0"} + assert "principalmente a descrição semântica quando disponível" in llm.prompt + assert "A ausência de tipo ou descrição NÃO impede a extração" in llm.prompt + assert "Em caso de dúvida razoável sobre a correspondência ou o valor, prefira null" in llm.prompt + assert "Nome do serviço, produto, item ou cobrança objeto da contestação." in llm.prompt diff --git a/tests/test_transaction_parameter_llm_precedence.py b/tests/test_transaction_parameter_llm_precedence.py index 1ea69fc..5e723d5 100644 --- a/tests/test_transaction_parameter_llm_precedence.py +++ b/tests/test_transaction_parameter_llm_precedence.py @@ -133,7 +133,7 @@ async def test_transaction_extractor_handles_multiple_parameters_without_hardcod @pytest.mark.asyncio -async def test_collecting_one_parameter_consumes_turn_before_intent_shift(tmp_path): +async def test_collecting_one_parameter_consumes_turn_after_classifier_continues(tmp_path): routing = tmp_path / "routing.yaml" routing.write_text( """ @@ -291,3 +291,165 @@ intents: assert decision.metadata["transaction_turn_consumed"] is True assert decision.metadata["transaction_confirmation_decision"] == "confirm" assert "transaction_interruption" not in decision.metadata + +@pytest.mark.asyncio +async def test_incompatible_intent_shift_wins_even_when_turn_could_fill_pending_parameter(tmp_path): + """A value-like turn cannot shield an incompatible new goal from intent-shift. + + Regression for the edge case where the active transaction is collecting a + field, but the same utterance clearly starts another transactional intent. + The framework must classify the goal first; parameter extraction is allowed + only after the classifier says CONTINUE. + """ + routing = tmp_path / "routing.yaml" + routing.write_text( + """ +router: + fallback_agent: support_agent + confidence_threshold: 0.70 +state_policies: + - state: COLLECTING_SUPPORT_PARAMETERS + agent: support_agent +intents: + - name: retail_support_exchange_return + agent: support_agent + priority: 20 + keywords: [devolver pedido] + - name: retail_order_cancel + agent: orders_agent + priority: 30 + keywords: [cancelar pedido] +""", + encoding="utf-8", + ) + + class _ShiftAndExtractLLM: + def __init__(self): + self.extraction_calls = 0 + self.shift_calls = 0 + + async def ainvoke(self, messages, **kwargs): + prompt = messages[-1]["content"] if isinstance(messages[-1], dict) else str(messages[-1]) + if kwargs.get("profile_name") == "transaction_parameter_extraction" or "pending_parameters:" in prompt: + self.extraction_calls += 1 + # This demonstrates the dangerous overlap: if extraction ran + # first, it could consume a field from the same utterance. + return json.dumps({"reason": "cancelar pedido PED-2002"}) + self.shift_calls += 1 + return json.dumps({ + "decision": "SHIFT", + "intent": "retail_order_cancel", + "agent": "orders_agent", + "confidence": 0.99, + "reason": "usuário passou a cancelar outro pedido", + }) + + llm = _ShiftAndExtractLLM() + settings = SimpleNamespace( + ROUTING_CONFIG_PATH=str(routing), + ENABLE_LLM_ROUTER=True, + ENABLE_ROUTE_STICKINESS=False, + ) + router = EnterpriseRouter(settings, llm=llm) + state = { + "user_text": "agora quero cancelar pedido PED-2002", + "sanitized_input": "agora quero cancelar pedido PED-2002", + "next_state": "COLLECTING_SUPPORT_PARAMETERS", + "transaction_status": "COLLECTING_PARAMETERS", + "missing_parameters": ["reason"], + "active_agent": "support_agent", + "intent": "state:COLLECTING_SUPPORT_PARAMETERS", + "active_transaction": { + "tool_name": "solicitar_devolucao", + "arguments": {"order_id": "PED-1001"}, + "status": "COLLECTING_PARAMETERS", + "started_from_intent": "retail_support_exchange_return", + "parameter_schema": {"reason": "string"}, + }, + } + + decision = await router.route(state) + + assert decision.intent == "retail_order_cancel" + assert decision.agent == "orders_agent" + assert decision.metadata["transaction_interruption"] == "intent_shift" + assert llm.shift_calls == 1 + assert llm.extraction_calls == 0 + + +@pytest.mark.asyncio +async def test_semantic_shift_wins_before_parameter_extraction_when_no_keyword_matches(tmp_path): + """Semantic SHIFT must win even if extraction could return a pending field.""" + routing = tmp_path / "routing.yaml" + routing.write_text( + """ +router: + fallback_agent: support_agent + confidence_threshold: 0.70 +state_policies: + - state: COLLECTING_SUPPORT_PARAMETERS + agent: support_agent +intents: + - name: retail_support_exchange_return + agent: support_agent + priority: 20 + keywords: [devolver pedido] + - name: retail_order_cancel + agent: orders_agent + priority: 30 + keywords: [] +""", + encoding="utf-8", + ) + + class _SemanticShiftAndExtractLLM: + def __init__(self): + self.extraction_calls = 0 + self.shift_calls = 0 + + async def ainvoke(self, messages, **kwargs): + prompt = messages[-1]["content"] if isinstance(messages[-1], dict) else str(messages[-1]) + if kwargs.get("profile_name") == "transaction_parameter_extraction" or "pending_parameters:" in prompt: + self.extraction_calls += 1 + return json.dumps({"reason": "encerrar a compra"}) + self.shift_calls += 1 + return json.dumps({ + "decision": "SHIFT", + "intent": "retail_order_cancel", + "agent": "orders_agent", + "confidence": 0.98, + "reason": "novo objetivo transacional incompatível", + }) + + llm = _SemanticShiftAndExtractLLM() + settings = SimpleNamespace( + ROUTING_CONFIG_PATH=str(routing), + ENABLE_LLM_ROUTER=True, + ENABLE_ROUTE_STICKINESS=False, + ) + router = EnterpriseRouter(settings, llm=llm) + state = { + "user_text": "mudei de ideia, quero encerrar a compra PED-2002", + "sanitized_input": "mudei de ideia, quero encerrar a compra PED-2002", + "next_state": "COLLECTING_SUPPORT_PARAMETERS", + "transaction_status": "COLLECTING_PARAMETERS", + "missing_parameters": ["reason"], + "active_agent": "support_agent", + "intent": "state:COLLECTING_SUPPORT_PARAMETERS", + "active_transaction": { + "tool_name": "solicitar_devolucao", + "arguments": {"order_id": "PED-1001"}, + "status": "COLLECTING_PARAMETERS", + "started_from_intent": "retail_support_exchange_return", + "parameter_schema": {"reason": "string"}, + }, + } + + decision = await router.route(state) + + assert decision.intent == "retail_order_cancel" + assert decision.agent == "orders_agent" + assert decision.metadata["transaction_interruption"] == "intent_shift" + assert decision.metadata["interruption_source"] == "semantic_classifier" + assert llm.shift_calls == 1 + assert llm.extraction_calls == 0 diff --git a/tests/test_transaction_state_regression_matrix.py b/tests/test_transaction_state_regression_matrix.py index 2e89dde..7471430 100644 --- a/tests/test_transaction_state_regression_matrix.py +++ b/tests/test_transaction_state_regression_matrix.py @@ -3,6 +3,7 @@ from types import SimpleNamespace import pytest from agent_framework.routing.enterprise_router import EnterpriseRouter +from agent_framework.routing.models import RouteDecision from agent_framework.runtime.agent_runtime import AgentRuntimeMixin @@ -428,3 +429,76 @@ async def test_matrix_terminal_stale_next_state_does_not_lock_generic_followup(s decision = await router.route(state) assert decision.method != "state" assert (decision.metadata or {}).get("transaction_state_recovered") is not True + +@pytest.mark.asyncio +@pytest.mark.parametrize("status", ["COMPLETED", "FAILED", "CANCELLED", "BLOCKED", "OUT_OF_SCOPE"]) +async def test_matrix_terminal_transaction_skips_route_continuity(status, tmp_path): + """Terminal transaction must release conversational stickiness on next turn.""" + router = _router(tmp_path, stickiness=False) + + class _ContinuityMustNotRun: + async def evaluate(self, state, *, intents): + raise AssertionError("route continuity must not run after terminal transaction") + + router.continuity = _ContinuityMustNotRun() + router.enable_llm_router = False + router.llm = None + state = { + "user_text": "nova solicitação sem keyword configurada", + "sanitized_input": "nova solicitação sem keyword configurada", + "transaction_status": status, + "next_state": None, + "active_transaction": None, + "active_agent": "orders_agent", + "intent": "retail_order_cancel", + "route_decision": {"agent": "orders_agent", "intent": "retail_order_cancel"}, + "context": {"session": {}}, + } + + decision = await router.route(state) + assert decision.method == "fallback" + assert decision.intent == "fallback" + + +@pytest.mark.asyncio +async def test_terminal_out_of_scope_allows_new_llm_intent_instead_of_continuity(tmp_path): + """Regression for OUT_OF_SCOPE -> unrelated/new semantic request on next turn.""" + router = _router(tmp_path, stickiness=False) + + class _ContinuityMustNotRun: + async def evaluate(self, state, *, intents): + raise AssertionError("stale continuity must not capture a post-terminal turn") + + router.continuity = _ContinuityMustNotRun() + router.enable_llm_router = True + router.llm = object() + + async def _fake_llm(text, state): + return RouteDecision( + route="vas_agent", + agent="vas_agent", + intent="retail_vas_cancel", + confidence=0.99, + reason="new semantic intent", + method="llm", + mcp_tools=["consultar_vas", "cancelar_vas_avulso"], + ) + + router._route_by_llm = _fake_llm + state = { + "user_text": "eu quero cancelar um serviço diferente", + "sanitized_input": "eu quero cancelar um serviço diferente", + "transaction_status": "OUT_OF_SCOPE", + "next_state": None, + "active_transaction": None, + "active_agent": "contestacao_agent", + "intent": "contas_contestation", + "route_decision": {"agent": "contestacao_agent", "intent": "contas_contestation"}, + "context": {"session": {}}, + } + + decision = await router.route(state) + assert decision.method == "llm" + assert decision.agent == "vas_agent" + assert decision.intent == "retail_vas_cancel" + assert decision.mcp_tools == ["consultar_vas", "cancelar_vas_avulso"] diff --git a/tests/unit/__pycache__/test_langgraph_checkpoint_interrupt_controlled.cpython-313-pytest-9.0.2.pyc b/tests/unit/__pycache__/test_langgraph_checkpoint_interrupt_controlled.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000..b34fe31 Binary files /dev/null and b/tests/unit/__pycache__/test_langgraph_checkpoint_interrupt_controlled.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/unit/__pycache__/test_langgraph_checkpoint_runtime_config.cpython-313-pytest-9.0.2.pyc b/tests/unit/__pycache__/test_langgraph_checkpoint_runtime_config.cpython-313-pytest-9.0.2.pyc index 35dd15d..e8f04d4 100644 Binary files a/tests/unit/__pycache__/test_langgraph_checkpoint_runtime_config.cpython-313-pytest-9.0.2.pyc and b/tests/unit/__pycache__/test_langgraph_checkpoint_runtime_config.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/unit/__pycache__/test_langgraph_checkpoint_saver.cpython-313-pytest-9.0.2.pyc b/tests/unit/__pycache__/test_langgraph_checkpoint_saver.cpython-313-pytest-9.0.2.pyc index 648fe5f..bb8f5cf 100644 Binary files a/tests/unit/__pycache__/test_langgraph_checkpoint_saver.cpython-313-pytest-9.0.2.pyc and b/tests/unit/__pycache__/test_langgraph_checkpoint_saver.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/unit/__pycache__/test_rag_kbdb_provider.cpython-313-pytest-9.0.2.pyc b/tests/unit/__pycache__/test_rag_kbdb_provider.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000..391cb27 Binary files /dev/null and b/tests/unit/__pycache__/test_rag_kbdb_provider.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/unit/__pycache__/test_rag_runtime_grounding.cpython-313-pytest-9.0.2.pyc b/tests/unit/__pycache__/test_rag_runtime_grounding.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000..151b578 Binary files /dev/null and b/tests/unit/__pycache__/test_rag_runtime_grounding.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/unit/__pycache__/test_resilient_checkpointer.cpython-313-pytest-9.0.2.pyc b/tests/unit/__pycache__/test_resilient_checkpointer.cpython-313-pytest-9.0.2.pyc index 8453472..e26f6bb 100644 Binary files a/tests/unit/__pycache__/test_resilient_checkpointer.cpython-313-pytest-9.0.2.pyc and b/tests/unit/__pycache__/test_resilient_checkpointer.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/unit/test_langgraph_checkpoint_interrupt_controlled.py b/tests/unit/test_langgraph_checkpoint_interrupt_controlled.py new file mode 100644 index 0000000..345a57c --- /dev/null +++ b/tests/unit/test_langgraph_checkpoint_interrupt_controlled.py @@ -0,0 +1,160 @@ +import base64 +import json +from types import SimpleNamespace + +import pytest + +from agent_framework.checkpoints.langgraph_saver import ( + RepositoryCheckpointSaver, + _TYPED_SERDE_MARKER, + _decode_checkpoint_value, + _encode_checkpoint_value, + _encode_pending_write_value, +) + + +Interrupt = type("Interrupt", (), {}) +Interrupt.__module__ = "langgraph.types" + + +class FakeSerde: + def dumps_typed(self, value): + assert type(value).__module__ == "langgraph.types" + assert type(value).__qualname__ == "Interrupt" + return "msgpack", b"interrupt-payload" + + def loads_typed(self, typed): + type_name, payload = typed + assert type_name == "msgpack" + assert payload == b"interrupt-payload" + return Interrupt() + + +class MemoryRepo: + def __init__(self): + self.value = None + + async def put(self, thread_id, value): + self.value = value + + async def get_latest(self, thread_id): + return self.value + + +def test_checkpoint_interrupt_only_in_special_channel_round_trips(): + serde = FakeSerde() + raw_interrupt = Interrupt() + checkpoint = { + "id": "cp1", + "channel_values": { + "__root__": { + "__interrupt__": [raw_interrupt], + "business": {"ok": True}, + }, + "ordinary": {"value": 1}, + }, + } + + encoded = _encode_checkpoint_value(serde, checkpoint) + leaf = encoded["channel_values"]["__root__"]["__interrupt__"][0] + assert leaf[_TYPED_SERDE_MARKER] is True + assert leaf["type"] == "msgpack" + assert base64.b64decode(leaf["data"]) == b"interrupt-payload" + assert encoded["channel_values"]["ordinary"] == {"value": 1} + + decoded = _decode_checkpoint_value(serde, encoded) + assert type(decoded["channel_values"]["__root__"]["__interrupt__"][0]).__module__ == "langgraph.types" + assert decoded["channel_values"]["ordinary"] == {"value": 1} + + +def test_checkpoint_interrupt_outside_special_channel_is_rejected(): + serde = FakeSerde() + checkpoint = { + "id": "cp1", + "channel_values": {"ordinary": [Interrupt()]}, + } + with pytest.raises(TypeError, match="não serializável"): + _encode_checkpoint_value(serde, checkpoint) + + +def test_checkpoint_unknown_object_inside_interrupt_channel_is_rejected(): + serde = FakeSerde() + + class Unknown: + pass + + checkpoint = { + "id": "cp1", + "channel_values": {"__root__": {"__interrupt__": [Unknown()]}}, + } + with pytest.raises(TypeError, match="não serializável"): + _encode_checkpoint_value(serde, checkpoint) + + +def test_plain_checkpoint_keeps_plain_json_shape(): + serde = FakeSerde() + checkpoint = { + "id": "cp1", + "channel_values": {"x": {"nested": [1, "a", True, None]}}, + "channel_versions": {"x": "1"}, + } + encoded = _encode_checkpoint_value(serde, checkpoint) + assert encoded == checkpoint + assert _TYPED_SERDE_MARKER not in json.dumps(encoded) + + +def test_pending_write_interrupt_requires_interrupt_branch(): + serde = FakeSerde() + encoded = _encode_pending_write_value( + serde, + {"__interrupt__": [Interrupt()]}, + path="$.pending_writes[t].__root__", + ) + assert encoded["__interrupt__"][0][_TYPED_SERDE_MARKER] is True + + with pytest.raises(TypeError, match="não serializável"): + _encode_pending_write_value( + serde, + {"ordinary": [Interrupt()]}, + path="$.pending_writes[t].__root__", + ) + + +def test_aput_encodes_only_checkpoint_interrupt_and_keeps_other_sections_strict(): + repo = MemoryRepo() + settings = SimpleNamespace(CHECKPOINT_REPOSITORY_PROVIDER="memory") + saver = RepositoryCheckpointSaver(settings, repository=repo) + saver.serde = FakeSerde() + + checkpoint = { + "id": "cp1", + "channel_values": {"__root__": {"__interrupt__": [Interrupt()]}}, + } + + import asyncio + asyncio.run(saver.aput( + {"configurable": {"thread_id": "t1"}}, + checkpoint, + {"source": "test"}, + {"x": 1}, + )) + + assert repo.value["metadata"] == {"source": "test"} + assert repo.value["new_versions"] == {"x": 1} + assert repo.value["checkpoint"]["channel_values"]["__root__"]["__interrupt__"][0][_TYPED_SERDE_MARKER] is True + + +def test_aput_does_not_enable_typed_serde_for_metadata(): + repo = MemoryRepo() + settings = SimpleNamespace(CHECKPOINT_REPOSITORY_PROVIDER="memory") + saver = RepositoryCheckpointSaver(settings, repository=repo) + saver.serde = FakeSerde() + + import asyncio + with pytest.raises(TypeError, match="metadata"): + asyncio.run(saver.aput( + {"configurable": {"thread_id": "t1"}}, + {"id": "cp1", "channel_values": {"x": 1}}, + {"bad": Interrupt()}, + {}, + )) diff --git a/tests/unit/test_langgraph_checkpoint_runtime_config.py b/tests/unit/test_langgraph_checkpoint_runtime_config.py index 4561861..6235931 100644 --- a/tests/unit/test_langgraph_checkpoint_runtime_config.py +++ b/tests/unit/test_langgraph_checkpoint_runtime_config.py @@ -1,6 +1,7 @@ from __future__ import annotations import asyncio +import pytest from types import SimpleNamespace from agent_framework.checkpoints.langgraph_saver import ( @@ -193,3 +194,104 @@ def test_checkpoint_serialization_never_silently_stringifies_unknown_objects() - with pytest.raises(TypeError, match="Checkpoint contém valor não serializável"): _strict_json_value({"channel_values": {"bad": RuntimeLike()}}, path="$.checkpoint") + + +def test_typed_serializer_bridge_is_limited_to_langgraph_interrupt_pending_write() -> None: + import base64 + import json + + Interrupt = type("Interrupt", (), {"__module__": "langgraph.types"}) + + class FakeSerde: + def dumps_typed(self, value): + assert type(value).__module__ == "langgraph.types" + assert type(value).__qualname__ == "Interrupt" + return ("fake_interrupt", json.dumps({"value": value.value}).encode("utf-8")) + + def loads_typed(self, payload): + type_name, raw = payload + assert type_name == "fake_interrupt" + obj = Interrupt() + obj.value = json.loads(raw.decode("utf-8"))["value"] + return obj + + interrupt = Interrupt() + interrupt.value = "pause" + repo = _Repo() + saver = RepositoryCheckpointSaver(SimpleNamespace(), repository=repo) + saver.serde = FakeSerde() + config = {"configurable": {"thread_id": "typed-thread"}} + + asyncio.run(saver.aput(config, {"id": "cp-typed", "channel_values": {}}, {}, {})) + # Mirrors the real LangGraph shape observed in the runtime log: + # pending_writes -> __root__ -> __interrupt__ -> [Interrupt(...)] + asyncio.run(saver.aput_writes( + config, + [("__root__", {"__interrupt__": [interrupt]})], + "task-typed", + )) + + persisted = repo.saved[1] + stored = persisted["pending_writes"][0]["value"]["__interrupt__"][0] + assert stored["__agent_framework_langgraph_typed__"] is True + assert stored["type"] == "fake_interrupt" + assert base64.b64decode(stored["data"]).decode("utf-8") == '{"value": "pause"}' + # Critical compatibility assertion: checkpoint/metadata/new_versions remain plain JSON. + assert persisted["checkpoint"] == {"id": "cp-typed", "channel_values": {}, "channel_versions": {}, "versions_seen": {}} + assert persisted["metadata"] == {} + + restored = saver._make_tuple(persisted) + pending = restored.pending_writes if hasattr(restored, "pending_writes") else restored["pending_writes"] + assert pending[0][0] == "task-typed" + assert pending[0][1] == "__root__" + restored_interrupt = pending[0][2]["__interrupt__"][0] + assert type(restored_interrupt).__module__ == "langgraph.types" + assert type(restored_interrupt).__qualname__ == "Interrupt" + assert restored_interrupt.value == "pause" + + +def test_non_interrupt_non_json_pending_write_still_fails_loudly() -> None: + class RuntimeLike: + pass + + repo = _Repo() + saver = RepositoryCheckpointSaver(SimpleNamespace(), repository=repo) + config = {"configurable": {"thread_id": "bad-pending-thread"}} + asyncio.run(saver.aput(config, {"id": "cp-bad", "channel_values": {}}, {}, {})) + + with pytest.raises(TypeError, match="Checkpoint contém valor não serializável"): + asyncio.run(saver.aput_writes(config, [("__root__", {"bad": RuntimeLike()})], "task-bad")) + + +def test_non_json_checkpoint_does_not_fall_back_to_typed_serde() -> None: + class RuntimeLike: + pass + + class ExplodingSerde: + def dumps_typed(self, value): + raise AssertionError("global typed serde fallback must not be used") + + repo = _Repo() + saver = RepositoryCheckpointSaver(SimpleNamespace(), repository=repo) + saver.serde = ExplodingSerde() + config = {"configurable": {"thread_id": "bad-checkpoint-thread"}} + + with pytest.raises(TypeError, match="Checkpoint contém valor não serializável"): + asyncio.run(saver.aput( + config, + {"id": "cp-bad", "channel_values": {"bad": RuntimeLike()}}, + {}, + {}, + )) + + +def test_json_pending_writes_remain_plain_json() -> None: + repo = _Repo() + saver = RepositoryCheckpointSaver(SimpleNamespace(), repository=repo) + config = {"configurable": {"thread_id": "plain-thread"}} + + asyncio.run(saver.aput(config, {"id": "cp-plain", "channel_values": {}}, {}, {})) + asyncio.run(saver.aput_writes(config, [("result", {"ok": True})], "task-plain")) + + persisted = repo.saved[1] + assert persisted["pending_writes"][0]["value"] == {"ok": True} diff --git a/tests/unit/test_rag_kbdb_provider.py b/tests/unit/test_rag_kbdb_provider.py new file mode 100644 index 0000000..b3d1722 --- /dev/null +++ b/tests/unit/test_rag_kbdb_provider.py @@ -0,0 +1,117 @@ +from types import SimpleNamespace + +import pytest + +from agent_framework.rag.rag_service import RagService + + +def _settings(**overrides): + data = dict( + RAG_PROVIDER="kbdb", RAG_TOP_K=5, + KBDB_DB_USER="kb_user", KBDB_DB_PASSWORD="kb_pwd", KBDB_DB_DSN="kb_tp", + KBDB_DB_WALLET_LOCATION=None, KBDB_DB_WALLET_PASSWORD=None, + ADB_USER=None, ADB_PASSWORD=None, ADB_DSN=None, + ADB_WALLET_LOCATION=None, ADB_WALLET_PASSWORD=None, + KBDB_SEARCH_TYPE="hybrid", KBDB_NODE_EXPANSION=True, + KBDB_NODE_MAX_RELATED=8, KBDB_GRAPH_CROSS_REF=False, + KBDB_MAX_CROSS_REF_HOPS=1, KBDB_DOCUMENT_TYPE="customer_safe", + KBDB_METADATA_JSON=None, KBDB_MIN_SCORE=None, + ) + data.update(overrides) + return SimpleNamespace(**data) + + +@pytest.mark.asyncio +async def test_kbdb_provider_adapts_serving_envelope(monkeypatch): + service = RagService(_settings()) + + def fake_search(query, k): + return { + "search_type": "hybrid", "confidence": "high", "low_confidence": False, + "top_score": 78.4, "warnings": [], + "seeds": [{"unit_id": 11, "rank": 1, "score": 78.4}], + "units": [ + {"unit_id": 10, "content": "passo anterior", "provenance": "parent"}, + {"unit_id": 11, "content": "resposta principal", "provenance": "seed"}, + ], + "documents": [{"document_id": 7, "title": "Politica"}], + } + + monkeypatch.setattr(service._kbdb, "_search_sync", fake_search) + result = await service.retrieve("qual a regra?", namespace="billing_agent") + + assert [d.id for d in result.documents] == ["10", "11"] + assert result.documents[1].score == 78.4 + assert result.metadata["provider"] == "kbdb" + assert result.metadata["confidence"] == "high" + assert "resposta principal" in result.as_prompt_context() + + +@pytest.mark.asyncio +async def test_kbdb_provider_is_serving_only(): + service = RagService(_settings()) + with pytest.raises(RuntimeError, match="serving-only"): + await service.add_documents(["texto"]) + + +def test_kbdb_connection_uses_same_wallet_semantics_without_adb_fallback(monkeypatch): + import sys + from agent_framework.rag.kbdb_service import KbdbRagService + + captured = {} + + class Defaults: + fetch_lobs = True + + class Connection: + def close(self): + captured["closed"] = True + + class FakeOracleDb: + defaults = Defaults() + + @staticmethod + def connect(**kwargs): + captured.update(kwargs) + return Connection() + + monkeypatch.setitem(sys.modules, "oracledb", FakeOracleDb) + settings = _settings( + KBDB_DB_USER="kb_user", + KBDB_DB_PASSWORD="kb_pwd", + KBDB_DB_DSN="kb_tp", + KBDB_DB_WALLET_LOCATION="/wallet/kb", + KBDB_DB_WALLET_PASSWORD="wallet_pwd", + ADB_USER="framework_user", + ADB_PASSWORD="framework_pwd", + ADB_DSN="framework_high", + ADB_WALLET_LOCATION="/wallet/framework", + ADB_WALLET_PASSWORD="framework_wallet_pwd", + ) + + service = KbdbRagService(settings) + with service._connect(): + pass + + assert captured["user"] == "kb_user" + assert captured["password"] == "kb_pwd" + assert captured["dsn"] == "kb_tp" + assert captured["config_dir"] == "/wallet/kb" + assert captured["wallet_location"] == "/wallet/kb" + assert captured["wallet_password"] == "wallet_pwd" + assert captured["closed"] is True + + +def test_kbdb_does_not_fallback_to_framework_adb_credentials(): + from agent_framework.rag.kbdb_service import KbdbRagService + + settings = _settings( + KBDB_DB_USER=None, + KBDB_DB_PASSWORD=None, + KBDB_DB_DSN=None, + ADB_USER="framework_user", + ADB_PASSWORD="framework_pwd", + ADB_DSN="framework_high", + ) + with pytest.raises(RuntimeError, match="KBDB_DB_USER"): + KbdbRagService(settings) diff --git a/tests/unit/test_rag_runtime_grounding.py b/tests/unit/test_rag_runtime_grounding.py new file mode 100644 index 0000000..407d068 --- /dev/null +++ b/tests/unit/test_rag_runtime_grounding.py @@ -0,0 +1,100 @@ +from types import SimpleNamespace + +import pytest + +from agent_framework.rag.rag_service import RagResult +from agent_framework.rag.vector_store import VectorDocument +from agent_framework.runtime.agent_runtime import AgentRuntimeMixin + + +class DummyRag: + def __init__(self): + self.calls = [] + + async def retrieve(self, query, *, namespace="default", graph_node=None, rewrite=False, k=None): + self.calls.append((query, namespace, graph_node, rewrite)) + return RagResult( + query=query, + documents=[VectorDocument(id="kb-1", content="Tarifação documentada", metadata={}, score=0.9)], + graph_neighbors=[], + latency_ms=3, + metadata={"provider": "kbdb", "confidence": "high", "low_confidence": False}, + ) + + +class Runtime(AgentRuntimeMixin): + pass + + +def _runtime(**settings): + rt = Runtime() + base = dict( + RAG_PROVIDER="kbdb", + SKIP_RAG_WHEN_MCP_SUFFICIENT=True, + ENABLE_RAG_QUERY_REWRITE=False, + ENABLE_RAG_CONTEXT_COMPRESSION=False, + RAG_GROUNDED_ONLY=False, + KBDB_GROUNDED_ONLY=True, + LONG_TERM_MEMORY_INJECT_CONTEXT=False, + ) + base.update(settings) + rt.settings = SimpleNamespace(**base) + rt.rag_service = DummyRag() + rt.guardrail_pipeline = None + return rt + + +@pytest.mark.asyncio +async def test_successful_mcp_does_not_skip_rag_without_explicit_sufficiency(): + rt = _runtime() + state = { + "agent_id": "telecom_contas", + "user_text": "Como funciona a tarifação do plano Infinity Pós?", + "sanitized_input": "Como funciona a tarifação do plano Infinity Pós?", + "mcp_results": [{"ok": True, "tool_name": "qualquer_tool", "result": {"plano": "Controle 50GB"}}], + } + + context, metadata = await rt._retrieve_rag_context(state) + + assert rt.rag_service.calls + assert "Tarifação documentada" in context + assert metadata["provider"] == "kbdb" + assert metadata["status"] == "executed" + assert metadata["document_count"] == 1 + + +@pytest.mark.asyncio +async def test_rag_skips_only_when_mcp_explicitly_declares_sufficiency(): + rt = _runtime() + state = { + "agent_id": "telecom_contas", + "user_text": "qual é meu plano?", + "sanitized_input": "qual é meu plano?", + "mcp_results": [{"ok": True, "result": {"plano": "Controle 50GB", "rag_sufficient": True}}], + } + + context, metadata = await rt._retrieve_rag_context(state) + + assert context == "" + assert not rt.rag_service.calls + assert metadata["reason"] == "mcp_explicitly_sufficient" + + +def test_kbdb_build_messages_injects_grounding_policy(): + rt = _runtime() + state = { + "user_text": "Como funciona?", + "sanitized_input": "Como funciona?", + "context": {}, + "business_context": {}, + } + messages = rt.build_messages( + state, + system_prompt="system", + mcp_results=[{"ok": True, "result": {"plano": "Controle"}}], + rag_context="", + rag_metadata={"provider": "kbdb", "enabled": True, "status": "empty", "document_count": 0}, + ) + user = next(m["content"] for m in messages if m["role"] == "user") + assert "Política de grounding obrigatória" in user + assert "Não complete lacunas usando conhecimento paramétrico" in user