diff --git a/README.md b/README.md index c2be83a..53be6cd 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ AgentWeave reduces the tools or agents visible to a model before inference while > **Your agent has 100+ tools. Don't make the model reason over all of them. Route first, then reason over a smaller relevant action space.** -**70.18% fewer tools exposed · 61.70% fewer input tokens · 50.95% lower mean local-model latency** +**Frozen BFCL-derived v6 study:** 70.18% fewer tools exposed · 61.70% fewer input tokens · 50.95% lower mean local-model latency **MCP · A2A · LangGraph · AutoGen · policy-aware routing · recovery · reproducible evaluation** **Quick links:** [30-second start](#30-second-start) · [Canonical runtime](#canonical-runtime) · [Results](#results-at-a-glance) · [0.7 quickstart](docs/QUICKSTART_0_7.md) · [MCP](docs/MCP_INTEGRATION.md) · [Contribute](CONTRIBUTING.md) · [Discussions](https://github.com/sauravsingla/agentweave/discussions) · [Road to 1.0](docs/ROAD_TO_1_0.md) · [Paper](https://arxiv.org/abs/2608.23078) · [Zenodo v0.7.0](https://zenodo.org/records/22913460) @@ -34,6 +34,8 @@ schema validation ↓ argument-aware authorization ↓ +replay / idempotency guard + ↓ execution ↓ bounded recovery / rediscovery @@ -43,7 +45,7 @@ AgentWeave does **not** replace MCP, LangGraph, AutoGen, A2A, or your model. It ## 30-second start -Install the base package from PyPI: +Install the base package from PyPI (Python 3.11+): ```bash pip install agentweave-router @@ -128,7 +130,7 @@ pytest -q `AgentWeaveRuntime` is the primary 0.7+ execution surface. It enforces one ordering instead of asking every integration to wire security correctly: ```text -catalog → scope → route → model → validate arguments → authorize → execute → recover +catalog → scope → route → model → validate arguments → authorize → replay guard → execute → recover ``` Key normalized contracts are `ToolSpec`, `ToolCall`, `ToolResult`, `ModelResponse`, `RunContext`, and `RuntimeResult`. @@ -137,7 +139,11 @@ Tool identity is separate from the function name shown to the model. This matter Model-generated arguments are validated against each `ToolSpec.input_schema` before authorization or execution. Authorization policies receive the resolved tool identity, arguments, provider/source metadata, tenant/security context, and model-visible set. Calls outside the routed set fail closed. -Every run also returns per-stage telemetry for catalog discovery, scope/routing, model calls, schema validation, authorization, execution, and recovery. +After authorization, v0.7.1 applies per-run replay/idempotency protection before invoking the executor. `ToolSpec.idempotency` supports `auto`, `none`, `call_id`, and `arguments`; `auto` uses argument-signature protection for high/critical-risk tools and call-ID protection for other tools. Only successful executions are cached, so failures remain eligible for bounded recovery without silently repeating a protected successful side effect. + +Executor-returned identity cannot override the canonical tool identity that passed routing, validation, and authorization. Conflicting executor identity is retained only as audit metadata, and structured tool results are serialized deterministically for model continuation. + +Every run also returns per-stage telemetry for catalog discovery, scope/routing, model calls, schema validation, authorization, replay reuse, execution, and recovery, together with replay and routing provenance. ### MCP runtime diff --git a/agentweave/__init__.py b/agentweave/__init__.py index 272fdc4..2feb88c 100644 --- a/agentweave/__init__.py +++ b/agentweave/__init__.py @@ -41,6 +41,10 @@ normalize_model_response, ) from .runtime_hardened import AgentWeaveRuntime +from . import runtime as _runtime_module + +# Keep direct module imports aligned with the canonical hardened runtime. +_runtime_module.AgentWeaveRuntime = AgentWeaveRuntime from .runtime_types import ( ModelResponse, RunContext, diff --git a/tests/test_runtime_public_import.py b/tests/test_runtime_public_import.py new file mode 100644 index 0000000..8fa52da --- /dev/null +++ b/tests/test_runtime_public_import.py @@ -0,0 +1,9 @@ +from agentweave import AgentWeaveRuntime as RootRuntime +from agentweave.runtime import AgentWeaveRuntime as ModuleRuntime +from agentweave.runtime_hardened import AgentWeaveRuntime as HardenedRuntime + + +def test_direct_runtime_import_uses_canonical_hardened_runtime(): + assert ModuleRuntime is RootRuntime + assert ModuleRuntime is HardenedRuntime + assert "arguments" in ModuleRuntime._IDEMPOTENCY_MODES