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 6d37940..dd2ef20 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__/extensions.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc index d17a94c..3c4a8cd 100644 Binary files a/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/__pycache__/gateway_policy_context.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/gateway_policy_context.cpython-313.pyc index 133a5dd..e88eacc 100644 Binary files a/libs/agent_framework/src/agent_framework/__pycache__/gateway_policy_context.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/__pycache__/gateway_policy_context.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 8a37c45..7c1f07a 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__/observer.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-313.pyc index 2bc834a..16c60ca 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__/runtime_mcp_gateway_adapter.cpython-313.pyc b/libs/agent_framework/src/agent_framework/__pycache__/runtime_mcp_gateway_adapter.cpython-313.pyc index 5f69ea0..1d040f9 100644 Binary files a/libs/agent_framework/src/agent_framework/__pycache__/runtime_mcp_gateway_adapter.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/__pycache__/runtime_mcp_gateway_adapter.cpython-313.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 9057572..f90a6c2 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__/composite_publisher.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-313.pyc index dbf930e..d80e926 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__/event_builder.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-313.pyc index 4dc7972..f26065c 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__/factory.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/factory.cpython-313.pyc index 0c6cf1f..f2c6660 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__/publisher.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/publisher.cpython-313.pyc index 1704f27..0839571 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__/tim_payload_mapper.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-313.pyc index a6ad0b6..d60075e 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_sequence.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_sequence.cpython-313.pyc index 2abecba..526cd36 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/providers/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/__init__.cpython-313.pyc index a31b573..b3d4315 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__/kafka.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-313.pyc index a2c3405..b84fe31 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__/langfuse.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/langfuse.cpython-313.pyc index 43b00a0..af8601c 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__/oci_streaming.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/oci_streaming.cpython-313.pyc index ad2f232..9bd8ab3 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__/pubsub.cpython-313.pyc b/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-313.pyc index c9ca37a..b3e7097 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/billing/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/billing/__pycache__/__init__.cpython-313.pyc index 91c5172..268522e 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__/usage_repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-313.pyc index 4854b89..8fe7115 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/cache/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-313.pyc index f6a00c9..a0808ef 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__/cache.cpython-313.pyc b/libs/agent_framework/src/agent_framework/cache/__pycache__/cache.cpython-313.pyc index df93216..f173ee8 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/channels/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/__init__.cpython-313.pyc index dfa3427..f3fdadf 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__/adapters.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-313.pyc index 13dd966..e099198 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__/base.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/base.cpython-313.pyc index 05d158a..2dfbd90 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__/gateway.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/gateway.cpython-313.pyc index c0573e5..9b06a47 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__/interruption.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc index 1708c0f..f51d600 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__/transcription.cpython-313.pyc b/libs/agent_framework/src/agent_framework/channels/__pycache__/transcription.cpython-313.pyc index 4478c95..eb0fdc0 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/checkpoints/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/__init__.cpython-313.pyc index 73cd760..38d35de 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__/checkpoint_repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/checkpoint_repository.cpython-313.pyc index 9079fe7..7466402 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__/langgraph_saver.cpython-313.pyc b/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-313.pyc index fff33ef..2c808c8 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/langgraph_saver.py b/libs/agent_framework/src/agent_framework/checkpoints/langgraph_saver.py index 18dac4a..2ca31b4 100644 --- a/libs/agent_framework/src/agent_framework/checkpoints/langgraph_saver.py +++ b/libs/agent_framework/src/agent_framework/checkpoints/langgraph_saver.py @@ -570,18 +570,42 @@ class RepositoryCheckpointSaver(BaseCheckpointSaver): async def aput_writes(self, config: dict[str, Any], writes: list[tuple[str, Any]], task_id: str, task_path: str = ""): thread_id = _thread_id(config) + requested_cfg = _durable_config(config) + requested_configurable = requested_cfg.get("configurable") if isinstance(requested_cfg.get("configurable"), dict) else {} + requested_checkpoint_id = str(requested_configurable.get("checkpoint_id") or "").strip() try: - latest = await self.repository.get_latest(thread_id) or {"thread_id": thread_id, "config": _durable_config(config), "checkpoint": {}, "metadata": {}} - except: + latest = await self.repository.get_latest(thread_id) or {"thread_id": thread_id, "config": requested_cfg, "checkpoint": {}, "metadata": {}} + except Exception: latest = { "thread_id": thread_id, - "config": _durable_config(config), + "config": requested_cfg, "checkpoint": {}, "metadata": {}, "pending_writes": [], } if isinstance(latest, dict): + # LangGraph may finish aput_writes() for an older super-step after a + # newer aput() has already persisted the next checkpoint. The + # repository is append-only, so blindly re-putting that older full + # payload would make the stale checkpoint the newest row and the next + # user turn would appear to "go back in time". Pending writes belong + # only to the checkpoint identified by config.checkpoint_id. If the + # durable latest checkpoint has already advanced, never append the + # stale payload as a new latest record. + latest_checkpoint = latest.get("checkpoint") if isinstance(latest.get("checkpoint"), dict) else {} + latest_checkpoint_id = str( + latest.get("checkpoint_id") + or latest_checkpoint.get("id") + or ((latest.get("config") or {}).get("configurable") or {}).get("checkpoint_id") + or "" + ).strip() + if ( + requested_checkpoint_id + and latest_checkpoint_id + and requested_checkpoint_id != latest_checkpoint_id + ): + return # Do not keep extending a persisted RunnableConfig across super-steps. # Rebuild the same canonical config that aget_tuple() will expose. latest["config"] = _canonical_checkpoint_config(latest, config) 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 778acb7..c2ae0f8 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__/agent_registry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-313.pyc index f805fab..ac1c17e 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__/settings.cpython-313.pyc b/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-313.pyc index 982ef1e..1678ae9 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/events/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/events/__pycache__/__init__.cpython-313.pyc index 4be3b30..7f8879c 100644 Binary files a/libs/agent_framework/src/agent_framework/events/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/events/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/events/__pycache__/oci_streaming.cpython-313.pyc b/libs/agent_framework/src/agent_framework/events/__pycache__/oci_streaming.cpython-313.pyc index 28c590a..2787c39 100644 Binary files a/libs/agent_framework/src/agent_framework/events/__pycache__/oci_streaming.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/events/__pycache__/oci_streaming.cpython-313.pyc differ 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 6ad88b1..7dcc568 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__/mcp_gateway_client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc index e735897..a661b74 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/global_supervisor/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/__init__.cpython-313.pyc index 6a97e1d..17a4e0e 100644 Binary files a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/client.cpython-313.pyc index b90fd8f..8d949d9 100644 Binary files a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/client.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/client.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/config.cpython-313.pyc b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/config.cpython-313.pyc index 885a41e..1cda59f 100644 Binary files a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/config.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/config.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/models.cpython-313.pyc index 000c9f6..c00fbcd 100644 Binary files a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/models.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/models.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/router.cpython-313.pyc b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/router.cpython-313.pyc index a93b618..5c36a51 100644 Binary files a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/router.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/router.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/session_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/session_store.cpython-313.pyc index 5df19df..f29f409 100644 Binary files a/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/session_store.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/global_supervisor/__pycache__/session_store.cpython-313.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 d3fa4e7..d0b2b90 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__/base.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc index 3dbd1ac..3609a1e 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__/config_loader.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc index 67e644d..750a7f1 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__/custom_rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc index b0e4dda..abe2d9d 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__/executor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/executor.cpython-313.pyc index 9f64e65..20cae0e 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/executor.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/executor.cpython-313.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 0a90f41..1c44d7b 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__/langgraph_adapters.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/langgraph_adapters.cpython-313.pyc index 0b3b871..8358bbd 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/__pycache__/langgraph_adapters.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/langgraph_adapters.cpython-313.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 ddedee0..3e23168 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__/output_supervisor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc index 3706435..863d19c 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__/parallel_executor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc index 8936cb0..e4bd26e 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__/pipeline.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc index 892395c..0634093 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__/rail_action.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-313.pyc index 13d5a9c..3dc9f8e 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_decision.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-313.pyc index 41e348e..da395c6 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_result.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-313.pyc index fa80334..4a31c5d 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__/rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-313.pyc index 2dbd728..8cb01ec 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/calibrated/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc index 21efb85..57f8c45 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__/_compat.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-313.pyc index 4708cfe..20682da 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__/config.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/config.cpython-313.pyc index 46bd8d0..1e3b36d 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/config.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/config.cpython-313.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 bce6081..e88ed6e 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__/contracts.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-313.pyc index 9316b89..2e692ed 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__/input_size.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/input_size.cpython-313.pyc index 9a27145..7d1f44a 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__/llm_adapter.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-313.pyc index fd4d59d..9772a2d 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_client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_client.cpython-313.pyc index 5044c00..caf4f1b 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_rails.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc index 156e566..fcdc277 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__/output_sanitization.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc index 1646570..a36bce5 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__/pipeline.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/pipeline.cpython-313.pyc index d3208e5..daa206a 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/prompts/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc index f2432c2..24c0300 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__/_context.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc index 8110ec9..84a4672 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__/ausencia_oferta_proativa.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc index a4b8461..d2948c8 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__/coerencia.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-313.pyc index 131939a..f78d1ba 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__/dlex_in.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-313.pyc index a91ffe5..ce28e29 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_out.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc index 57a065b..d7b0e3d 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__/fallback.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-313.pyc index b290cb9..f18b89e 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__/fraseologia.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fraseologia.cpython-313.pyc index 885cc2c..87681d3 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__/out_of_scope.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc index 2ca4865..dbf7799 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__/pinj.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc index 5d759df..528d266 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__/ragsec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-313.pyc index 3f2d1a9..384cd68 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__/revprec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-313.pyc index 1bf5cbc..dde7d46 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__/safe_out.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/safe_out.cpython-313.pyc index d1787ac..2774d2d 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/safe_out.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/safe_out.cpython-313.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 09c1849..84f78f3 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__/toxicidade_output.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/toxicidade_output.cpython-313.pyc index f49141f..9600db0 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/ausencia_oferta_proativa.py b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/ausencia_oferta_proativa.py index 88d977e..9686035 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 @@ -62,6 +62,19 @@ Decida na ordem, PARE no primeiro match: mesmo alvo, a fala do agente que apenas pede CONFIRMACAO da transacao e allowed=true. A confirmacao NAO precisa repetir a justificativa do cliente ("nao reconheco", "esta caro" etc.); o pedido transacional anterior basta. + CONTINUIDADE POR CANAL ALTERNATIVO: se a acao transacional foi explicitamente + pedida pelo cliente para o mesmo alvo e a execucao por este canal falhou, ficou + indisponivel ou nao pode ser concluida, orientar o cliente sobre COMO concluir + ESSA MESMA acao em outro canal oficial e allowed=true. Isso nao cria uma nova + oferta: apenas informa o caminho operacional para cumprir o pedido ja existente. + Bloqueie somente se a orientacao introduzir outra acao, outro alvo ou ampliar o + escopo alem do que o cliente pediu. + EVIDENCIA ESTRUTURADA: quando o contexto operacional trouxer alvo solicitado/ + resolvido e resultado da execucao (sucesso, falha parcial, item nao encontrado), + trate esses campos como evidencia autoritativa do pedido atual. Se a resposta + orientar outro canal para o MESMO alvo cuja execucao falhou, allowed=true, mesmo + que a ultima mensagem do cliente seja apenas uma confirmacao como "sim". + Vale tambem trocar uma variante transacional por outra DA MESMA FAMILIA sobre o MESMO escopo, sempre limitada ao valor JA COBRADO no item (ressarcimento <-> devolucao <-> reembolso <-> cancelamento <-> credito em fatura): negar o dobro e diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/revprec.py b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/revprec.py index 52bd28b..7158db3 100644 --- a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/revprec.py +++ b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/revprec.py @@ -1,92 +1,54 @@ -"""Prompt do rail REVPREC — "o agente disse que cancelou algo?". - -Reescrito em 2026-08-06. A versão anterior (207 linhas, algoritmo de 9 passos, saída -`{allowed,label,reason,score}`) julgava PROMESSA FUTURA sem autorização e, por -construção, deixava passar exatamente o caso que interessa: o passo 2 dela dava OK a -"resultado no PASSADO ou PRESENTE". Foi descartada inteira. - -O rail agora responde UMA pergunta binária: a última fala do agente afirma que um -cancelamento / retirada de valor / contestação já aconteceu? - -Por que isso funciona sem falso positivo na ação legítima: o rail só roda quando o -ORQUESTRADOR responde em TEXTO. Quando a ação acontece de verdade, ela vem de uma tool -call — e `apply_output_rails` sai antes dos rails LLM quando há `tool_calls` no turno -(pipeline.py, invariante do early-exit), assim como a fala canônica do -`ResponseComposer` entra com `skip_rails=True`. Ou seja: se esta pergunta chega ao LLM, -o agente está afirmando uma ação que ele NÃO tem tool para executar. - -Saída BINÁRIA com polaridade INVERTIDA em relação a PINJ/COER: aqui `1` = achou a -afirmação = bloqueia; `0` = fala limpa. A pergunta fica na forma positiva ("disse que -cancelou?") porque é ela que dá acurácia; a inversão mora no `llm_client` -(`_BINARY_BLOCK_DIGIT`). - -Duas fronteiras que o prompt precisa manter, e que os casos da suíte travam: - - **histórico**: um cancelamento feito do jeito certo em turno anterior FICA no - histórico e não foi avaliado por este rail; só o bloco "Resposta:" é julgado; - - **protocolo**: o número de protocolo só é emitido depois da tool rodar, então uma - fala que o traz relata execução real → 0. -""" +"""REVPREC: detecta verbalização de resultado operacional sem evidência atual.""" from __future__ import annotations def build_revprec_prompt(text: str, context: str = "") -> str: - """Monta o prompt do rail REVPREC. + """Compara a fala candidata com a evidência estrutural do turno atual. - Args: - text: última fala gerada pelo agente (a que será julgada). - context: histórico já formatado por ``prompts._context.format_context_block`` - (a última fala do agente é PODADA de lá — ela vem em ``text``). - - Returns: - Prompt cuja resposta esperada é um único caractere: ``1`` ou ``0``. + Polaridade: 1 = a fala afirma conclusão/efeito operacional não comprovado ou + contradito pela evidência; 0 = permitido. """ - return f"""Você audita UMA fala do agente de fatura do provedor e responde 1 ou 0. + return f"""Você audita UMA fala de um agente de atendimento TIM. -O agente NÃO executa cancelamento, contestação nem retirada de valor. Quando a ação -acontece de verdade, é o sistema que responde ao cliente — nunca esta fala. Logo, -afirmar aqui que já cancelou/retirou/contestou é sempre falso. +Sua tarefa NÃO é decidir se a frase "soa" como ação concluída. Sua tarefa é comparar +as afirmações da RESPOSTA com a EVIDÊNCIA REAL DO TURNO ATUAL. -ANTES DE TUDO: se a fala traz NÚMERO DE PROTOCOLO — um ou vários, no formato "PRT..." -bruto, vocalizado ("pê erre tê nove cê dois...") ou dígitos depois da palavra protocolo — -responda 0 e pare. O protocolo só é emitido DEPOIS de a ação rodar de verdade; com ele a -fala relata execução real, inclusive quando RECAPITULA cancelamentos já feitos, por mais -concluída que soe. +Responda 1 SOMENTE quando a resposta afirmar que uma ação/efeito operacional já foi +concluído (por exemplo cancelamento, contestação, retirada de valor, crédito, reembolso, +envio ou alteração) e essa conclusão NÃO estiver suportada pela evidência atual, ou +estiver contradita por ela. -Responda 1 quando a fala AFIRMA que um cancelamento, retirada de valor, contestação ou -reembolso JÁ ACONTECEU. Ex.: "cancelamento confirmado", "já foi cancelado", "cancelado -com sucesso", "cancelei o serviço", "retiramos o valor", "sua contestação foi -registrada", "o reembolso já foi processado", "a cobrança não vai mais aparecer porque -removi o serviço". +Responda 0 quando: +- a evidência atual comprova a ação/resultado afirmado; +- a resposta apenas explica dados de fatura, cobrança, desconto, plano, valor, data, + status ou motivo presentes na evidência; +- a resposta pede confirmação/permissão ou solicita parâmetro; +- a resposta anuncia uma ação futura sem afirmar que já ocorreu; +- a resposta nega que a ação ocorreu; +- a resposta expressa ausência de evidência ou incerteza; +- não existe afirmação de conclusão operacional. -Responda 0 em todo o resto. Em particular: -- PERGUNTA ou PEDIDO DE PERMISSÃO, mesmo citando cancelamento: "Podemos seguir com o - cancelamento do serviço X, no valor de R$ 12,00, você confirma?", "Gostaria de - cancelar esse serviço?", "Posso seguir?". -- ESCOPO ou intenção reconhecida, sem ação feita: "Entendi que você deseja falar sobre - os serviços X e Y. Correto?", "Vou verificar isso para você". -- PROMESSA sem afirmar execução: "vou cancelar", "seguiremos com o cancelamento, aguarde - um instante", "o valor será retirado da sua fatura". Aqui a pergunta é se a ação foi - DADA COMO FEITA; anúncio do que vem depois não é. -- DESCRIÇÃO DA FATURA, não ação do agente: "Foi removido um desconto de R$ 6,00", "foi - adicionada a cobrança do X", "esse serviço foi cobrado em duas datas" — isso compara - faturas e explica cobranças; não cancela nada. -- ORIENTAÇÃO a outro canal: "ligue para *144 e solicite o cancelamento", "pelo app do - parceiro você consegue cancelar". -- NEGATIVA de ação: "não consigo cancelar por aqui", "ainda não cancelei", "esse serviço - não pode ser cancelado neste atendimento". -- EXPLICAÇÃO, valor, data, encerramento, saudação, ou qualquer assunto que não seja - ação de cancelamento dada como feita. +REGRAS IMPORTANTES: +1. Use SOMENTE a evidência do bloco EVIDÊNCIA ATUAL para provar execução. Não use + histórico, memória ou suposições. + Julgue somente a fala do bloco "Resposta:"; qualquer texto fora desse bloco é contexto. +2. Se a evidência mostra sucesso/COMPLETED e contém os fatos afirmados, responda 0. +3. Se a evidência mostra falha/erro/não executado e a resposta afirma sucesso, responda 1. +4. Se não existe evidência de execução e a resposta afirma que uma ação transacional já + foi realizada, responda 1. +5. Descrição de algo que aconteceu na conta/fatura (ex.: desconto expirou, cobrança foi + lançada) não é "ação prematura" se isso estiver suportado pelos dados atuais. +6. PROTOCOLO é evidência auxiliar, não regra absoluta: valide junto com a evidência atual. +7. DESCRIÇÃO DA FATURA (cobrança, desconto, data, status, motivo) não é execução de ação + pelo agente quando estiver sustentada pelos dados atuais. -O HISTÓRICO é só contexto. Um cancelamento feito corretamente em turno anterior APARECE -lá e NÃO conta — ele não passou por esta auditoria e não é o que se julga agora. Julgue -somente a fala do bloco "Resposta:". - -------------------------------------{context} -Resposta: +---------------- EVIDÊNCIA ATUAL ---------------- +{context or '[]'} +---------------- RESPOSTA ---------------- {text} ------------------------------------- +-------------------------------------------------- -A fala do bloco "Resposta:" afirma que um cancelamento, retirada de valor ou -contestação já aconteceu? +A RESPOSTA contém alguma afirmação de resultado operacional concluído que NÃO esteja +suportada (ou esteja contradita) pela EVIDÊNCIA ATUAL? -Responda APENAS 1 ou 0, sem mais nada.""" +Responda APENAS 1 ou 0.""" diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/__init__.cpython-313.pyc index d5a6bac..81b6a1f 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/supervision_template.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/supervision_template.cpython-313.pyc index 545c415..8cf6db9 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/supervision_template.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/supervision_template.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/tts_rules.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/tts_rules.cpython-313.pyc index 8708f30..99288c8 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/tts_rules.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/shared/__pycache__/tts_rules.cpython-313.pyc differ 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 b332bab..679d83d 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__/alcada.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-313.pyc index 0d98db3..5001ab4 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__/anatel.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-313.pyc index 31ea4b6..93af918 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__/confirmation.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc index 6b3a60e..5d65f58 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__/dlex_in.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc index 99a2d6d..2d893db 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_out.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc index 1697f9a..7152ce1 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__/ragsec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-313.pyc index e62ed42..26340d5 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__/revprec.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-313.pyc index 0de4a46..19b310a 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__/tox.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-313.pyc index 5af6e2e..d82a04f 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/supervision/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/__init__.cpython-313.pyc index 6cc5508..da950c0 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/correspondencia_item.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/correspondencia_item.cpython-313.pyc index aeec185..d6a00dc 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/correspondencia_item.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/correspondencia_item.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/groundedness.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/groundedness.cpython-313.pyc index 2a76c07..1308c95 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/groundedness.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/groundedness.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/intencao_cancelar.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/intencao_cancelar.cpython-313.pyc index fefa284..db9779e 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/intencao_cancelar.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/intencao_cancelar.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/quantidade_coerente.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/quantidade_coerente.cpython-313.pyc index 6c3b8f9..6d3357e 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/quantidade_coerente.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/quantidade_coerente.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/servico_correto.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/servico_correto.cpython-313.pyc index 9525536..fbe5429 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/servico_correto.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/servico_correto.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/verbalizacao_prematura.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/verbalizacao_prematura.cpython-313.pyc index 110ac50..f0cbbe3 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/verbalizacao_prematura.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/supervision/__pycache__/verbalizacao_prematura.cpython-313.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 2eb99a9..a00ad76 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__/alcada.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc index 6a456ac..e72c6d2 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__/oos_blocklist.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/oos_blocklist.cpython-313.pyc index 4f7fe94..a8d83f4 100644 Binary files a/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/oos_blocklist.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/oos_blocklist.cpython-313.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 414c3b8..65efbd1 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__/tox_blocklist.cpython-313.pyc b/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-313.pyc index 34abe3d..32b0d82 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/framework_llm_client.py b/libs/agent_framework/src/agent_framework/guardrails/framework_llm_client.py index f3d4e6a..bce98a5 100644 --- a/libs/agent_framework/src/agent_framework/guardrails/framework_llm_client.py +++ b/libs/agent_framework/src/agent_framework/guardrails/framework_llm_client.py @@ -396,6 +396,7 @@ async def classify_with_framework_llm( cliente LLM paralelo fora da arquitetura do framework. """ selected_profile = _selected_profile_for_task(task, profile_name) + owned_llm = llm is None llm = _ensure_framework_llm(llm) # USE_MOCK_LLM remains useful for local development, but it must not hide an @@ -420,27 +421,39 @@ async def classify_with_framework_llm( if task in _BINARY_TASKS else "Responda apenas JSON válido, sem markdown." ) - raw = await llm.ainvoke( - [ - {"role": "system", "content": system_instruction}, - {"role": "user", "content": prompt}, - ], - profile_name=selected_profile, - component_name=selected_component, - generation_name=selected_generation, - ) - output = _extract_text(raw) - if task == "TOXOUT": - return {"text": output} - if not output: - return {"allowed": True, "label": "EMPTY", "reason": ""} - if task in _BINARY_TASKS: - block_digit = _BINARY_BLOCK_DIGIT.get(task, "0") - digits = [ch for ch in output if ch in "01"] - allowed = digits[-1] != block_digit if digits else True - return { - "allowed": allowed, - "label": "OK" if allowed else task, - "reason": "" if allowed else _BINARY_TASKS[task], - } - return _parse_json(output) + try: + raw = await llm.ainvoke( + [ + {"role": "system", "content": system_instruction}, + {"role": "user", "content": prompt}, + ], + profile_name=selected_profile, + component_name=selected_component, + generation_name=selected_generation, + ) + output = _extract_text(raw) + if task == "TOXOUT": + return {"text": output} + if not output: + return {"allowed": True, "label": "EMPTY", "reason": ""} + if task in _BINARY_TASKS: + block_digit = _BINARY_BLOCK_DIGIT.get(task, "0") + digits = [ch for ch in output if ch in "01"] + allowed = digits[-1] != block_digit if digits else True + return { + "allowed": allowed, + "label": "OK" if allowed else task, + "reason": "" if allowed else _BINARY_TASKS[task], + } + return _parse_json(output) + finally: + if owned_llm and llm is not None: + close = getattr(llm, "aclose", None) + if callable(close): + try: + result = close() + if hasattr(result, "__await__"): + await result + except Exception: + # Guardrail classification result must not be replaced by a cleanup failure. + pass diff --git a/libs/agent_framework/src/agent_framework/guardrails/rails.py b/libs/agent_framework/src/agent_framework/guardrails/rails.py index 187e557..fcfb31b 100644 --- a/libs/agent_framework/src/agent_framework/guardrails/rails.py +++ b/libs/agent_framework/src/agent_framework/guardrails/rails.py @@ -338,9 +338,44 @@ class LoopRail(Guardrail): code = "VLOOP" stage = "input" + @staticmethod + def _transaction_status(ctx: dict[str, Any]) -> str: + status = str(ctx.get("transaction_status") or "").strip().upper() + if status: + return status + active_transaction = ctx.get("active_transaction") + if isinstance(active_transaction, dict): + return str(active_transaction.get("status") or "").strip().upper() + return "" + async def evaluate(self, text: str, context: dict[str, Any]) -> RailDecision: + ctx = _ctx(context) + transaction_status = self._transaction_status(ctx) + + # A short confirmation (for example ``sim``/``não``) may legitimately + # appear several times in the same session because each transaction has + # its own confirmation boundary. VLOOP protects against conversational + # repetition; it must not consume the input that belongs to an active + # transaction awaiting confirmation. The transaction runtime/classifier + # remains responsible for deciding whether the utterance is actually a + # valid confirm/reject response. + if transaction_status == "AWAITING_CONFIRMATION": + return RailDecision( + code=self.code, + allowed=True, + reason="continuidade_transacional:AWAITING_CONFIRMATION", + sanitized_text=text, + metadata={ + "history_window": len(list(ctx.get("history_texts") or [])[-6:]), + "repeated": False, + "mechanism": "deterministic_transaction_bypass", + "transaction_status": transaction_status, + "calibrated": True, + }, + ) + normalized = _lower(text).strip() - history = [_lower(h).strip() for h in _ctx(context).get("history_texts", [])[-6:]] + history = [_lower(h).strip() for h in ctx.get("history_texts", [])[-6:]] repeated = history.count(normalized) >= 2 if normalized else False return RailDecision( code=self.code, diff --git a/libs/agent_framework/src/agent_framework/idempotency.py b/libs/agent_framework/src/agent_framework/idempotency.py index 1b67040..af39ceb 100644 --- a/libs/agent_framework/src/agent_framework/idempotency.py +++ b/libs/agent_framework/src/agent_framework/idempotency.py @@ -13,10 +13,20 @@ logger = logging.getLogger("agent_framework.idempotency") class IdempotencyStore: """Namespace idempotente apoiado no storage genérico do framework.""" - def __init__(self, backend: Any, *, namespace: str = "idempotency", ttl_seconds: int | None = None): + def __init__( + self, + backend: Any, + *, + namespace: str = "idempotency", + ttl_seconds: int | None = None, + fallback_backend: Any | None = None, + fail_open: bool = False, + ): self.backend = backend self.namespace = namespace self.ttl_seconds = ttl_seconds + self.fallback_backend = fallback_backend + self.fail_open = bool(fail_open) @staticmethod def canonical_key(*parts: Any) -> str: @@ -27,13 +37,58 @@ class IdempotencyStore: return f"{self.namespace}:{key}" async def get(self, key: str) -> Any | None: - return await self.backend.get(self._key(key)) + scoped = self._key(key) + try: + value = await self.backend.get(scoped) + if value is not None: + return value + except Exception as exc: + if not self.fail_open or self.fallback_backend is None: + raise + logger.warning("Falha no backend primário de idempotência em get(%s); usando fallback em memória: %s", scoped, exc) + if self.fallback_backend is not None: + try: + return await self.fallback_backend.get(scoped) + except Exception as exc: + logger.warning("Falha no fallback de idempotência em get(%s): %s", scoped, exc) + return None async def set(self, key: str, value: Any, *, ttl_seconds: int | None = None) -> None: - await self.backend.set(self._key(key), value, ttl_seconds if ttl_seconds is not None else self.ttl_seconds) + scoped = self._key(key) + ttl = ttl_seconds if ttl_seconds is not None else self.ttl_seconds + primary_ok = False + try: + await self.backend.set(scoped, value, ttl) + primary_ok = True + except Exception as exc: + if not self.fail_open or self.fallback_backend is None: + raise + logger.warning("Falha no backend primário de idempotência em set(%s); usando fallback em memória: %s", scoped, exc) + if self.fallback_backend is not None: + try: + await self.fallback_backend.set(scoped, value, ttl) + except Exception as exc: + logger.warning("Falha no fallback de idempotência em set(%s): %s", scoped, exc) + if not primary_ok and not self.fail_open: + raise async def delete(self, key: str) -> None: - await self.backend.delete(self._key(key)) + scoped = self._key(key) + primary_error = None + try: + await self.backend.delete(scoped) + except Exception as exc: + primary_error = exc + if not self.fail_open or self.fallback_backend is None: + raise + logger.warning("Falha no backend primário de idempotência em delete(%s); limpando fallback: %s", scoped, exc) + if self.fallback_backend is not None: + try: + await self.fallback_backend.delete(scoped) + except Exception as exc: + logger.warning("Falha no fallback de idempotência em delete(%s): %s", scoped, exc) + if primary_error is not None and not self.fail_open: + raise class InMemoryIdempotencyStore(IdempotencyStore): @@ -81,4 +136,12 @@ def create_idempotency_store(settings, *, namespace: str = "idempotency", requir raise RuntimeError(f"Provider de idempotência durável não suportado: {provider}") logger.warning("Provider de idempotência %s não suportado; usando memória", provider) backend = InMemoryCache() - return IdempotencyStore(backend, namespace=namespace, ttl_seconds=ttl) + fail_open = bool(getattr(settings, "IDEMPOTENCY_FAIL_OPEN", not durable_required)) + fallback_backend = InMemoryCache() if fail_open and not isinstance(backend, InMemoryCache) else None + return IdempotencyStore( + backend, + namespace=namespace, + ttl_seconds=ttl, + fallback_backend=fallback_backend, + fail_open=fail_open, + ) 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 54d3fb4..262a3b6 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__/mcp_mapper.cpython-313.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-313.pyc index b05721b..78250ff 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__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/models.cpython-313.pyc index e051ab9..8444ca7 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__/resolver.cpython-313.pyc b/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-313.pyc index dd8b638..ddd7be6 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/judges/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/__pycache__/__init__.cpython-313.pyc index 4da852f..fd1f7bb 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__/judge.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc index d258c05..1954bc6 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/calibrated/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-313.pyc index 65c8262..4b91dab 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__/_compat.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/_compat.cpython-313.pyc index 8039405..f430abb 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/_compat.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/_compat.cpython-313.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 b3f67a3..2e44150 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__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/models.cpython-313.pyc index 198f6bf..8a14436 100644 Binary files a/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/models.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/models.cpython-313.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 6c7a3a6..0ab8d48 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__/aluc.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-313.pyc index 02e8cbf..6c3e14d 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__/csi.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-313.pyc index b088da7..63a7acf 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__/fallback.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-313.pyc index 26557c2..c3493b7 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__/rqlt.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-313.pyc index b0a5252..032224b 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__/vctn.cpython-313.pyc b/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-313.pyc index 71820d9..6ba3e52 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/judge.py b/libs/agent_framework/src/agent_framework/judges/judge.py index fbac24f..6e13a2f 100644 --- a/libs/agent_framework/src/agent_framework/judges/judge.py +++ b/libs/agent_framework/src/agent_framework/judges/judge.py @@ -490,7 +490,10 @@ class JudgePipeline: async def evaluate_all(self, question, answer, context): if not self.enabled or not self.judges: return [] - ctx = context or {} + # Judges must evaluate business evidence, not the full operational/checkpoint + # object. External judges receive the same bounded context contract as native + # judges so recursive workflow/session payloads cannot overflow the model. + ctx = _compact_judge_context(context or {}) transactional = self._is_transactional_context(ctx) # Transactional turns take precedence over sampling. Sampling is only @@ -601,6 +604,81 @@ def _normalize_judge_specs(config: dict[str, Any]) -> list[dict[str, Any]]: return specs + +_JUDGE_CONTEXT_DROP_KEYS = { + 'state', 'vars', 'session', 'session_metadata', 'original_context', + 'agent_profile', 'business_events', 'trace', 'nodes', 'input', + 'raw_llm_answer', 'headers', 'request_kwargs', 'response_headers', +} + +def _compact_judge_context( + context: dict[str, Any], + *, + max_total_chars: int = 36000, + max_field_chars: int = 12000, + max_depth: int = 6, + max_items: int = 24, +) -> dict[str, Any]: + """Return a bounded, business-focused judge context. + + The full workflow/checkpoint remains available for telemetry and audit. Judges + receive only a compact projection so native and external implementations share + the same safety contract. + """ + def compact(value: Any, depth: int = 0) -> Any: + if depth >= max_depth: + return '[conteúdo aninhado omitido]' if isinstance(value, (dict, list, tuple, set)) else value + if isinstance(value, dict): + out: dict[str, Any] = {} + for idx, (key, raw) in enumerate(value.items()): + if idx >= max_items: + out['_omitted_fields'] = max(0, len(value) - max_items) + break + key_s = str(key) + if key_s.lower() in _JUDGE_CONTEXT_DROP_KEYS: + continue + out[key_s] = compact(raw, depth + 1) + return out + if isinstance(value, (list, tuple, set)): + seq = list(value) + out = [compact(item, depth + 1) for item in seq[:max_items]] + if len(seq) > max_items: + out.append(f'[+{len(seq)-max_items} itens omitidos]') + return out + if isinstance(value, str) and len(value) > max_field_chars: + return value[:max_field_chars] + '…[texto truncado]' + return value + + compacted = compact(context) + if not isinstance(compacted, dict): + compacted = {'context': compacted} + + # Enforce a final aggregate budget without discarding the top-level transaction + # signals used by sampling/always-run decisions. + try: + rendered = json.dumps(compacted, ensure_ascii=False, default=str) + except Exception: + rendered = str(compacted) + if len(rendered) <= max_total_chars: + return compacted + + priority = ( + 'transaction_status', 'confirmation_required', 'confirmation_received', + 'route', 'intent', 'transactional_tools', 'tool_policy_result', + 'selected_tool_call', 'pending_tool_call', + ) + bounded: dict[str, Any] = {k: compacted.get(k) for k in priority if k in compacted} + for key in ('mcp_results', 'transaction_evidence', 'evidence'): + if key not in compacted: + continue + value = compacted[key] + try: + text = json.dumps(value, ensure_ascii=False, default=str) + except Exception: + text = str(value) + bounded[key] = text[:max_field_chars] + ('…[contexto do judge truncado]' if len(text) > max_field_chars else '') + return bounded + def _extract_evidence(context: dict[str, Any]) -> str: if not context: return '' 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 a4090b4..da7e219 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__/base.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-313.pyc index 8e26ef8..972b662 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__/profile_resolver.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-313.pyc index d41c1e5..c2b4ecf 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__/providers.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc index 0a77eca..4039e6c 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__/structured_output.cpython-313.pyc b/libs/agent_framework/src/agent_framework/llm/__pycache__/structured_output.cpython-313.pyc index b526051..f55398b 100644 Binary files a/libs/agent_framework/src/agent_framework/llm/__pycache__/structured_output.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/llm/__pycache__/structured_output.cpython-313.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 index 75df3f7..05014a0 100644 Binary files a/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-313.pyc 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/providers.py b/libs/agent_framework/src/agent_framework/llm/providers.py index ee91acd..b20c298 100644 --- a/libs/agent_framework/src/agent_framework/llm/providers.py +++ b/libs/agent_framework/src/agent_framework/llm/providers.py @@ -569,6 +569,32 @@ class OCICompatibleOpenAIProvider(LLMProvider): ) raise + async def aclose(self) -> None: + """Close all cached OpenAI-compatible clients inside their owning event loop. + + Temporary providers are created by legacy guardrail compatibility bridges. + Explicitly closing them before ``asyncio.run`` returns prevents the OpenAI/httpx + client finalizer from trying to close transports after the loop is already gone. + Persistent application-owned providers can call the same method at shutdown. + """ + clients = list(self._clients.values()) + self._clients.clear() + self.client = None + for client in clients: + close = getattr(client, "close", None) + aclose = getattr(client, "aclose", None) + try: + if callable(aclose): + result = aclose() + if hasattr(result, "__await__"): + await result + elif callable(close): + result = close() + if hasattr(result, "__await__"): + await result + except Exception: + logger.exception("Erro ao fechar cliente OpenAI-compatible") + def _using_langfuse_openai(self) -> bool: if self.client is None: return False 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 c440061..c872622 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__/client.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/client.cpython-313.pyc index de3c3cf..d8ae516 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__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-313.pyc index 5b0803f..a64e270 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__/registry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-313.pyc index e6a2dee..16e0b00 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__/tool_policy.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-313.pyc index 16e939b..ca72d39 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_router.cpython-313.pyc b/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-313.pyc index da436b7..bc53c02 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/memory/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/__init__.cpython-313.pyc index 44095a3..fab016e 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__/long_term_extractor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_extractor.cpython-313.pyc index 591a085..ab2e2fc 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_memory.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_memory.cpython-313.pyc index c464653..087fa9a 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_models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_models.cpython-313.pyc index 8d02e7c..08efccd 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_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/long_term_store.cpython-313.pyc index 36bbd51..d2853be 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__/message_history.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/message_history.cpython-313.pyc index 94cb5f1..aa77e38 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__/summary_memory.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc index 1afbf13..71ed337 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_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_store.cpython-313.pyc index 1f66214..7274f40 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/models/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/__init__.cpython-313.pyc index 1b6d5e7..06466e2 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__/identity.cpython-313.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-313.pyc index 43a155c..ffe4903 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__/session.cpython-313.pyc b/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-313.pyc index 7270228..b1d2104 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/observability/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-313.pyc index 3c6ba54..d0cd341 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__/code_mapper.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-313.pyc index e5b7f76..0ae593e 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/code_mapper.cpython-313.pyc 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__/context.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/context.cpython-313.pyc index 9a40d3a..d783e51 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__/control_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/control_events.cpython-313.pyc index 5bb1e55..42f45e6 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/control_events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/control_events.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/observability/__pycache__/decorators.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/decorators.cpython-313.pyc index 0566f5f..aa273b0 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/decorators.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/decorators.cpython-313.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 d07ea53..f8903e5 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__/grl_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/grl_events.cpython-313.pyc index 278d210..aaeab24 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/grl_events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/grl_events.cpython-313.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 cef8b73..eccd280 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__/ic_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-313.pyc index 614da67..96696e6 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__/informational_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/informational_events.cpython-313.pyc index b22ea7b..8295681 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/informational_events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/informational_events.cpython-313.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 4393995..718770e 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__/langfuse_enterprise.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/langfuse_enterprise.cpython-313.pyc index 447bf41..228abc6 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/langfuse_enterprise.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/langfuse_enterprise.cpython-313.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 46ef8ad..5634f6c 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__/llm_advisors.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/llm_advisors.cpython-313.pyc index 56ff1e8..169138a 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__/noc_contract.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_contract.cpython-313.pyc index 96eb960..7d81579 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_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_events.cpython-313.pyc index 6f66900..3471004 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_events.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/noc_events.cpython-313.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 b127e43..e4fbb18 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__/observer.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/observer.cpython-313.pyc index fcf3352..14bb5c4 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__/otel.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/otel.cpython-313.pyc index acef38b..e75b197 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__/streaming_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_events.cpython-313.pyc index 7096133..69cab22 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_exporter.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_exporter.cpython-313.pyc index b40b78b..a7df198 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_exporter.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/streaming_exporter.cpython-313.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 a945454..b6eae43 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__/tim_backoffice_contract.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/tim_backoffice_contract.cpython-313.pyc index 42851b9..1a5f3fc 100644 Binary files a/libs/agent_framework/src/agent_framework/observability/__pycache__/tim_backoffice_contract.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/observability/__pycache__/tim_backoffice_contract.cpython-313.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 22641f9..584ec9f 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__/workflow_events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-313.pyc index 110b3a8..da593ed 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/oci/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-313.pyc index f973264..48f6406 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__/auth.cpython-313.pyc b/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-313.pyc index 2cfd0d4..548cdcc 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/persistence/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/__init__.cpython-313.pyc index 1d4abf9..41a9bdd 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__/mongodb_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/mongodb_store.cpython-313.pyc index 6d9acc9..763cec2 100644 Binary files a/libs/agent_framework/src/agent_framework/persistence/__pycache__/mongodb_store.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/persistence/__pycache__/mongodb_store.cpython-313.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 c2542f2..162b640 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__/sqlite_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/persistence/__pycache__/sqlite_store.cpython-313.pyc index c65869a..a7bfda1 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/oracle_store.py b/libs/agent_framework/src/agent_framework/persistence/oracle_store.py index 45a62a0..2cd4ba5 100644 --- a/libs/agent_framework/src/agent_framework/persistence/oracle_store.py +++ b/libs/agent_framework/src/agent_framework/persistence/oracle_store.py @@ -412,6 +412,22 @@ class OracleStore: out.append({"id": row[0], "session_id": row[1], "event_name": row[2], "payload": _json_loads(v.read() if hasattr(v,"read") else v, {}), "created_at": row[4]}) return out + @staticmethod + def _normalize_datetime_for_compare(value): + """Normaliza timestamps Oracle/Python para comparação segura em UTC. + + Oracle DATE/TIMESTAMP pode retornar datetime sem tzinfo, enquanto o clock do + framework é timezone-aware. Para TTL/cache, datetime naive é interpretado + como UTC, que é o padrão usado pelo framework ao persistir expirações. + """ + if value is None: + return None + if not isinstance(value, datetime): + return value + if value.tzinfo is None or value.utcoffset() is None: + return value.replace(tzinfo=timezone.utc) + return value.astimezone(timezone.utc) + async def cache_get(self, key: str): return await asyncio.to_thread(self._cache_get, key) @@ -421,8 +437,9 @@ class OracleStore: cur.execute(f"select VALUE_JSON, EXPIRES_AT from {self.t('CACHE_ENTRY')} where CACHE_KEY=:1", [key]) row=cur.fetchone() if not row: return None - expires=row[1] - if expires and expires < self.now(): + expires = self._normalize_datetime_for_compare(row[1]) + now = self._normalize_datetime_for_compare(self.now()) + if expires and expires < now: cur.execute(f"delete from {self.t('CACHE_ENTRY')} where CACHE_KEY=:1", [key]) return None v=row[0] 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 f6e0008..220e3fe 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__/renderers.cpython-313.pyc b/libs/agent_framework/src/agent_framework/presentation/__pycache__/renderers.cpython-313.pyc index f18daaf..0e257d5 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/rag/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/__init__.cpython-313.pyc index e603cf1..eeabd1b 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__/embedding_provider.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-313.pyc index d7dfa6f..bf4541b 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__/graph_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-313.pyc index 59d7933..4b40d3c 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__/ingest.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-313.pyc index 09ce71d..f43963f 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__/kbdb_service.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc index 1dd6804..1c3214e 100644 Binary files a/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc 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__/rag_service.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc index 0c15984..ac74e8a 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__/vector_store.cpython-313.pyc b/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-313.pyc index 9cad746..2775a7a 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/repositories/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/repositories/__pycache__/__init__.cpython-313.pyc index 8d7e513..557f93a 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__/session_repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-313.pyc index dae4f49..90f2737 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/routing/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc index 40b6f74..d187825 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__/config_loader.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-313.pyc index a29af09..5dc21fb 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__/continuity.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/continuity.cpython-313.pyc index ab458a2..170e4f4 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__/enterprise_router.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc index 8e15dab..9c23d1a 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__/models.cpython-313.pyc b/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc index bff8801..369446f 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/runtime/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-313.pyc index 9a2d984..da962e4 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__/agent_runtime.cpython-313.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc index 295a6c5..a519316 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__/transaction_input.cpython-313.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_input.cpython-313.pyc index 20a83fd..4ca250e 100644 Binary files a/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_input.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_input.cpython-313.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 index 6f1b17f..48591af 100644 Binary files a/libs/agent_framework/src/agent_framework/runtime/__pycache__/transaction_parameters.cpython-313.pyc 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/agent_runtime.py b/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py index 153052d..10b05ee 100644 --- a/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py +++ b/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py @@ -1923,7 +1923,15 @@ class AgentRuntimeMixin: transaction_id: str | None = None, ) -> dict[str, Any]: current = state.get("active_transaction") if isinstance(state.get("active_transaction"), dict) else {} - txid = transaction_id or current.get("transaction_id") or str(uuid.uuid4()) + current_is_active = self._transaction_is_active(state) and bool(current.get("transaction_id")) + txid = transaction_id or (current.get("transaction_id") if current_is_active else None) or str(uuid.uuid4()) + normalized_arguments = dict(arguments or {}) + if not current_is_active and transaction_id is None: + # workflow_execution_id is transaction-scoped. A value left by a + # completed/failed transaction must never seed a new one in the same + # session. A paused workflow is resumed through pending_domain_workflow + # / retomar_workflow, not by opening a new transaction with this field. + normalized_arguments.pop("workflow_execution_id", None) if str(current.get("tool_name") or "") != str(tool_name): pre_validation = state.get("transaction_pre_validation") pre_validation = pre_validation if isinstance(pre_validation, dict) else {} @@ -1951,7 +1959,7 @@ class AgentRuntimeMixin: tx = { "transaction_id": txid, "tool_name": tool_name, - "arguments": dict(arguments or {}), + "arguments": normalized_arguments, "status": status, "started_from_intent": current.get("started_from_intent") or state.get("intent"), "requires": list(policy.get("requires") or getattr(cfg, "requires", []) or []), @@ -1962,7 +1970,14 @@ class AgentRuntimeMixin: "parameter_conversational_context": parameter_context or "", "user_claims_are_evidence": False if parameter_context else current.get("user_claims_are_evidence", False), } + # Invariant: the operational transaction and the scalar lifecycle status + # must always describe the same interaction. A previous terminal status + # (for example COMPLETED) must not survive after a new transaction is + # installed, otherwise the next input-boundary normalization may clear the + # newly created confirmation/parameter latches as if they belonged to the + # previous transaction. state["active_transaction"] = tx + state["transaction_status"] = status return tx @staticmethod @@ -3312,6 +3327,119 @@ class AgentRuntimeMixin: sections.append(f"Últimas mensagens completas da conversa:\n{rendered}") return sections + # ------------------------------------------------------------------ + # LLM context compaction + # ------------------------------------------------------------------ + _LLM_CONTEXT_DROP_KEYS = { + # Runtime/checkpoint internals are useful for audit/debug, but must not be + # recursively injected into an answering prompt. They frequently contain + # copies of the original request, session and previous workflow outputs. + "state", "vars", "session", "session_metadata", "original_context", + "agent_profile", "business_events", "trace", "nodes", "input", + # Provider / transport diagnostics do not add business grounding. + "raw_llm_answer", "headers", "request_kwargs", "response_headers", + } + + def _compact_llm_value( + self, + value: Any, + *, + max_chars: int = 16000, + max_depth: int = 6, + max_items: int = 24, + ) -> str: + """Render structured context for an LLM without checkpoint explosions. + + The operational state may intentionally retain complete workflow/MCP evidence + for auditability. Prompt context has a different contract: it contains the + business facts needed for the current answer, not recursive runtime objects. + This renderer therefore drops framework-internal recursive keys, bounds list + sizes/depth and finally enforces a hard character budget. + """ + truncated = False + + def compact(item: Any, depth: int = 0) -> Any: + nonlocal truncated + if depth >= max_depth: + if isinstance(item, (dict, list, tuple, set)): + truncated = True + return "[conteúdo aninhado omitido]" + return item + if isinstance(item, dict): + out: dict[str, Any] = {} + for idx, (key, raw) in enumerate(item.items()): + if idx >= max_items: + truncated = True + out["_omitted_fields"] = max(0, len(item) - max_items) + break + key_s = str(key) + if key_s.lower() in self._LLM_CONTEXT_DROP_KEYS: + truncated = True + continue + out[key_s] = compact(raw, depth + 1) + return out + if isinstance(item, (list, tuple, set)): + seq = list(item) + if len(seq) > max_items: + truncated = True + out = [compact(child, depth + 1) for child in seq[:max_items]] + if len(seq) > max_items: + out.append(f"[+{len(seq) - max_items} itens omitidos]") + return out + if isinstance(item, str) and len(item) > 4000: + truncated = True + return item[:4000] + "…[texto truncado]" + return item + + try: + rendered = json.dumps(compact(value), ensure_ascii=False, default=str, separators=(",", ":")) + except Exception: + rendered = str(value) + if len(rendered) > max_chars: + truncated = True + rendered = rendered[:max_chars] + "…[contexto truncado pelo framework]" + if truncated: + return rendered + "\n[observação: payload técnico/duplicado foi compactado; fatos preservados dentro do orçamento]" + return rendered + + @staticmethod + def _is_context_length_error(exc: Exception) -> bool: + text = str(exc).lower() + markers = ( + "maximum context length", + "max context length", + "context_length_exceeded", + "input length", + "too many tokens", + ) + return any(marker in text for marker in markers) + + def _compact_messages_for_retry( + self, + messages: list[dict[str, str]], + *, + max_total_chars: int = 60000, + ) -> list[dict[str, str]]: + """Emergency second-pass budget used only after provider rejection.""" + if not messages: + return messages + system_budget = min(20000, max_total_chars // 3) + remaining = max_total_chars - system_budget + compacted: list[dict[str, str]] = [] + for index, message in enumerate(messages): + content = str(message.get("content") or "") + role = str(message.get("role") or "user") + if role == "system": + budget = system_budget + else: + non_system_left = max(1, sum(1 for m in messages[index:] if str(m.get("role") or "") != "system")) + budget = max(4000, remaining // non_system_left) + remaining = max(0, remaining - budget) + if len(content) > budget: + content = content[:budget] + "…[mensagem compactada após limite de contexto]" + compacted.append({"role": role, "content": content}) + return compacted + # ------------------------------------------------------------------ # Messages / LLM / cache # ------------------------------------------------------------------ @@ -3337,19 +3465,26 @@ class AgentRuntimeMixin: f"Intent/rota escolhidos pelo framework:\nintent={state.get('intent')} route={state.get('route')}", ]) if include_business_context: - sections.append(f"BusinessContext canônico:\n{runtime.business_context or '[sem business_context]'}") + sections.append( + "BusinessContext canônico:\n" + + self._compact_llm_value(runtime.business_context or "[sem business_context]", max_chars=6000) + ) if mcp_results is not None: - sections.append(f"Resultados MCP normalizados pelo framework:\n{mcp_results}") + sections.append( + "Resultados MCP normalizados pelo framework:\n" + + self._compact_llm_value(mcp_results, max_chars=18000) + ) transaction_evidence = self.transaction_evidence_for_turn(state, mcp_results) if transaction_evidence: sections.append( "Evidências operacionais de transações anteriores relevantes ao recurso atual " - f"(persistidas pelo framework, não inferidas pela memória conversacional):\n{transaction_evidence}" + "(persistidas pelo framework, não inferidas pela memória conversacional):\n" + + self._compact_llm_value(transaction_evidence, max_chars=12000) ) if rag_context is not None: 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}") + sections.append("Metadados RAG:\n" + self._compact_llm_value(rag_metadata, max_chars=6000)) 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": @@ -3363,7 +3498,7 @@ class AgentRuntimeMixin: "- 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}") + sections.append(f"{title}:\n" + self._compact_llm_value(value, max_chars=10000)) return MessageBuilder(state).system(system_prompt).user("\n\n".join(sections)).build() async def _cache_get(self, key: str): @@ -3425,7 +3560,33 @@ class AgentRuntimeMixin: return cached if telemetry: await telemetry.event("cache.llm.miss", {"agent": agent_name, "key": key}, kind="cache") - answer = await self.llm.ainvoke(messages, profile_name=agent_name, component_name=agent_name, generation_name=f"llm.{agent_name}") + try: + answer = await self.llm.ainvoke( + messages, + profile_name=agent_name, + component_name=agent_name, + generation_name=f"llm.{agent_name}", + ) + except Exception as exc: + if not self._is_context_length_error(exc): + raise + retry_messages = self._compact_messages_for_retry(messages) + if telemetry: + await telemetry.event( + "llm.context.compacted_retry", + { + "agent": agent_name, + "original_chars": sum(len(str(m.get("content") or "")) for m in messages), + "retry_chars": sum(len(str(m.get("content") or "")) for m in retry_messages), + }, + kind="llm", + ) + answer = await self.llm.ainvoke( + retry_messages, + profile_name=agent_name, + component_name=agent_name, + generation_name=f"llm.{agent_name}.context_retry", + ) await self._cache_set(key, answer, ttl) return answer diff --git a/libs/agent_framework/src/agent_framework/security/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/security/__pycache__/__init__.cpython-313.pyc index 2ee9826..e4e8343 100644 Binary files a/libs/agent_framework/src/agent_framework/security/__pycache__/__init__.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/security/__pycache__/__init__.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/security/__pycache__/authentication.cpython-313.pyc b/libs/agent_framework/src/agent_framework/security/__pycache__/authentication.cpython-313.pyc index afc8a70..b09249e 100644 Binary files a/libs/agent_framework/src/agent_framework/security/__pycache__/authentication.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/security/__pycache__/authentication.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/security/__pycache__/factory.cpython-313.pyc b/libs/agent_framework/src/agent_framework/security/__pycache__/factory.cpython-313.pyc index 4f325e3..615bb37 100644 Binary files a/libs/agent_framework/src/agent_framework/security/__pycache__/factory.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/security/__pycache__/factory.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/security/__pycache__/installer.cpython-313.pyc b/libs/agent_framework/src/agent_framework/security/__pycache__/installer.cpython-313.pyc index a3812c9..aaed83c 100644 Binary files a/libs/agent_framework/src/agent_framework/security/__pycache__/installer.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/security/__pycache__/installer.cpython-313.pyc differ diff --git a/libs/agent_framework/src/agent_framework/security/__pycache__/middleware.cpython-313.pyc b/libs/agent_framework/src/agent_framework/security/__pycache__/middleware.cpython-313.pyc index 1bbe572..de845c0 100644 Binary files a/libs/agent_framework/src/agent_framework/security/__pycache__/middleware.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/security/__pycache__/middleware.cpython-313.pyc differ 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 2df1153..c4a831a 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__/events.cpython-313.pyc b/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc index a22fe76..ff08431 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/supervisor/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-313.pyc index 950d0ec..a1defb9 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__/router_supervisor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/router_supervisor.cpython-313.pyc index 2c9b2f6..3359cc7 100644 Binary files a/libs/agent_framework/src/agent_framework/supervisor/__pycache__/router_supervisor.cpython-313.pyc and b/libs/agent_framework/src/agent_framework/supervisor/__pycache__/router_supervisor.cpython-313.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 1da17c2..08a3aab 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/workflows/__pycache__/__init__.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/__init__.cpython-313.pyc index 4ab9955..0bd6d73 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__/graph.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/graph.cpython-313.pyc index b2e3712..3a3c269 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__/input_contract.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/input_contract.cpython-313.pyc index a39e10e..4ca4c0b 100644 Binary files a/libs/agent_framework/src/agent_framework/workflows/__pycache__/input_contract.cpython-313.pyc 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 0bbab8f..730f0f6 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__/registry.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/registry.cpython-313.pyc index f6f021a..93500be 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__/repository.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/repository.cpython-313.pyc index 7825dc1..eee267b 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__/runtime.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-313.pyc index e19b5ce..011d24d 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__/tool_executor.cpython-313.pyc b/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc index 07ffe89..b80ecdc 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/runtime.py b/libs/agent_framework/src/agent_framework/workflows/runtime.py index c171010..c82d010 100644 --- a/libs/agent_framework/src/agent_framework/workflows/runtime.py +++ b/libs/agent_framework/src/agent_framework/workflows/runtime.py @@ -649,6 +649,12 @@ class WorkflowRuntime: state = await graph.ainvoke(Command(resume=resume_value), config=config) phase = "aget_state_resume" snapshot = await graph.aget_state(config) + # Some LangGraph/checkpointer combinations keep exposing a durable + # interrupt from the previous pause after resume. Once execution has + # advanced to a node whose active edge is END, terminal state is + # authoritative and that interrupt is stale. + if self._is_structurally_terminal(definition, state): + return self._result_from_state(definition, execution_id, state) interrupts = self._snapshot_interrupts(snapshot) if interrupts: pause = interrupts[-1] @@ -662,8 +668,6 @@ class WorkflowRuntime: pause=pause if isinstance(pause, dict) else {"value": pause}, trace=list(state.get("trace") or []), ) - if self._is_structurally_terminal(definition, state): - return self._result_from_state(definition, execution_id, state) if getattr(snapshot, "next", None): raise RuntimeError( "LangGraph retornou trabalho pendente sem interrupt real em estado não terminal; " 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 303bb84..1674055 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_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 4e295d2..d3d04a8 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/test_llm_context_compaction.py b/tests/test_llm_context_compaction.py new file mode 100644 index 0000000..cdfcad2 --- /dev/null +++ b/tests/test_llm_context_compaction.py @@ -0,0 +1,93 @@ +import pytest + +from agent_framework.runtime.agent_runtime import AgentRuntimeMixin + + +class DummyRuntime(AgentRuntimeMixin): + def __init__(self, llm=None): + self.llm = llm + self.cache = None + self.telemetry = None + self.settings = None + + +class ContextFailThenOkLLM: + def __init__(self): + self.calls = [] + + async def ainvoke(self, messages, **kwargs): + self.calls.append((messages, kwargs)) + if len(self.calls) == 1: + raise RuntimeError("Input length (134212) exceeds model's maximum context length (131072)") + return "ok" + + +def test_compact_llm_value_drops_recursive_runtime_payload_but_keeps_business_facts(): + runtime = DummyRuntime() + payload = { + "result": { + "subject": "Tamboro Mensal", + "success": True, + "service": {"details": {"valor": "14,99"}}, + "state": {"session": {"secret": "must-not-leak"}, "huge": "x" * 20000}, + "business_events": [{"payload": "x" * 20000}], + } + } + rendered = runtime._compact_llm_value(payload, max_chars=8000) + assert "Tamboro Mensal" in rendered + assert "14,99" in rendered + assert "must-not-leak" not in rendered + assert "business_events" not in rendered + assert len(rendered) < 9000 + + +def test_build_messages_bounds_mcp_and_transaction_evidence(): + runtime = DummyRuntime() + giant = { + "tool_name": "cancelar_vas_avulso", + "ok": True, + "result": { + "subject": "Tamboro Mensal", + "validatedAmount": "14,99", + "state": {"payload": "x" * 100000}, + "services": [{"name": f"svc-{i}", "details": {"valor": "1,00"}} for i in range(100)], + }, + } + state = { + "user_text": "isso mesmo, pode cancelar", + "sanitized_input": "isso mesmo, pode cancelar", + "intent": "state:WAITING_CONFIRMATION", + "route": "contestacao_agent", + "business_context": {"customer_key": "11999999999"}, + "transaction_evidence": [{ + "transaction_id": "tx-1", + "tool_name": "cancelar_vas_avulso", + "arguments": {"subject": "Tamboro Mensal"}, + "status": "COMPLETED", + "result": giant, + }], + } + messages = runtime.build_messages(state, system_prompt="system", mcp_results=[giant]) + total = sum(len(m["content"]) for m in messages) + joined = "\n".join(m["content"] for m in messages) + assert total < 50000 + assert "Tamboro Mensal" in joined + assert "14,99" in joined + assert "x" * 5000 not in joined + + +@pytest.mark.asyncio +async def test_context_length_error_retries_once_with_compacted_messages(): + llm = ContextFailThenOkLLM() + runtime = DummyRuntime(llm=llm) + messages = [ + {"role": "system", "content": "s" * 30000}, + {"role": "user", "content": "u" * 120000}, + ] + answer = await runtime._invoke_llm_cached({}, "ContestacaoAgent", messages) + assert answer == "ok" + assert len(llm.calls) == 2 + first_chars = sum(len(m["content"]) for m in llm.calls[0][0]) + second_chars = sum(len(m["content"]) for m in llm.calls[1][0]) + assert second_chars < first_chars + assert second_chars <= 61000 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 index b2826cd..98335bb 100644 Binary files a/tests/unit/__pycache__/test_langgraph_checkpoint_interrupt_controlled.cpython-313-pytest-9.0.2.pyc 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 ba19220..0037d7d 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/test_langgraph_checkpoint_runtime_config.py b/tests/unit/test_langgraph_checkpoint_runtime_config.py index 6235931..2922549 100644 --- a/tests/unit/test_langgraph_checkpoint_runtime_config.py +++ b/tests/unit/test_langgraph_checkpoint_runtime_config.py @@ -295,3 +295,31 @@ def test_json_pending_writes_remain_plain_json() -> None: persisted = repo.saved[1] assert persisted["pending_writes"][0]["value"] == {"ok": True} + + +def test_stale_pending_write_cannot_replace_newer_checkpoint() -> None: + """A delayed write for cp1 must never make cp1 latest after cp2 exists.""" + repo = _Repo() + saver = RepositoryCheckpointSaver(SimpleNamespace(), repository=repo) + + cfg0 = {"configurable": {"thread_id": "tx-thread"}} + cp1_cfg = asyncio.run(saver.aput(cfg0, {"id": "cp1", "v": 1, "channel_values": {"transaction_status": "COMPLETED"}}, {}, {})) + cp2_cfg = asyncio.run(saver.aput(cp1_cfg, {"id": "cp2", "v": 1, "channel_values": {"transaction_status": "AWAITING_CONFIRMATION", "confirmation_required": True}}, {}, {})) + + # Simulates aput_writes from the older cp1 finishing after cp2 was persisted. + asyncio.run(saver.aput_writes(cp1_cfg, [("result", {"old": True})], "late-task")) + + assert repo.saved is not None + latest = repo.saved[1] + assert latest["checkpoint_id"] == "cp2" + assert latest["checkpoint"]["channel_values"]["transaction_status"] == "AWAITING_CONFIRMATION" + assert "pending_writes" not in latest or not any( + isinstance(item, dict) and item.get("task_id") == "late-task" + for item in latest.get("pending_writes", []) + ) + + # A write for the actual latest checkpoint is still accepted. + asyncio.run(saver.aput_writes(cp2_cfg, [("result", {"new": True})], "current-task")) + latest = repo.saved[1] + assert latest["checkpoint_id"] == "cp2" + assert any(item.get("task_id") == "current-task" for item in latest.get("pending_writes", [])) diff --git a/tests/unit/test_workflow_terminal_snapshot_semantics.py b/tests/unit/test_workflow_terminal_snapshot_semantics.py index 7436db5..1fe4498 100644 --- a/tests/unit/test_workflow_terminal_snapshot_semantics.py +++ b/tests/unit/test_workflow_terminal_snapshot_semantics.py @@ -188,3 +188,31 @@ def test_snapshot_interrupts_deduplicates_task_and_persisted_shapes(tmp_path: Pa ) assert runtime._snapshot_interrupts(snapshot) == [payload] + +@pytest.mark.asyncio +async def test_aresume_ignores_stale_interrupt_after_advancing_to_terminal_node(tmp_path: Path, monkeypatch): + _write_workflow(tmp_path) + runtime = WorkflowRuntime(FileWorkflowRepository(tmp_path), actions=WorkflowActionRegistry()) + state = _terminal_state("exec-stale") + # Shape observed after resuming invoice_explanation: the durable snapshot can + # still expose the interrupt from the old pause although current_node has + # already advanced to the terminal handoff/finalization node. + stale = SimpleNamespace(value={"node": "old_pause", "prompt": "old prompt"}) + task = SimpleNamespace(interrupts=(stale,)) + snapshot = SimpleNamespace(next=("finish__continue",), tasks=(task,), values=state) + monkeypatch.setattr(runtime, "_compile", lambda definition: _FakeGraph(state, snapshot)) + + langgraph_module = ModuleType("langgraph") + types_module = ModuleType("langgraph.types") + class _Command: + def __init__(self, **kwargs): + self.kwargs = kwargs + types_module.Command = _Command + monkeypatch.setitem(sys.modules, "langgraph", langgraph_module) + monkeypatch.setitem(sys.modules, "langgraph.types", types_module) + + result = await runtime.aresume("terminal", "exec-stale", "nao") + + assert result.status == "COMPLETED" + assert result.pause is None + assert result.state["current_node"] == "finish"