Skip to content

feat(agentcore): Add operational Policy tools sub-package#3193

Open
sundargthb wants to merge 1 commit intoawslabs:mainfrom
sundargthb:policy-tools-subpackage
Open

feat(agentcore): Add operational Policy tools sub-package#3193
sundargthb wants to merge 1 commit intoawslabs:mainfrom
sundargthb:policy-tools-subpackage

Conversation

@sundargthb
Copy link
Copy Markdown
Contributor

Fixes

Summary

Adds the AgentCore Policy primitive to the unified
amazon-bedrock-agentcore-mcp-server as an operational sub-package
(Pattern A), following the same pattern as Memory, Runtime, Browser,
and Code Interpreter.

Exposes 15 MCP tools covering all 14 public Policy control-plane
APIs plus a comprehensive static guide:

  • 5 Policy Engine toolspolicy_engine_{create,get,update,delete,list}
  • 5 Policy CRUD toolspolicy_{create,get,update,delete,list}
  • 4 Policy Generation toolspolicy_generation_{start,get,list,list_assets}
  • 1 Guide toolget_policy_guide

All operations go through bedrock-agentcore-control — Policy has no
data plane, so the sub-package uses a single cached boto3 client.


Cost & Gating — Read This Before Approving

The unified MCP server autoregisters tools; AI coding agents can
discover and call any registered tool without explicit user action.
Some Policy APIs incur AWS charges, and one (policy generation) is
potentially expensive. This PR applies the same safeguards we added
after the Code Interpreter billing incident.

Per-tool risk tier

Billable (incur AWS charges — COST WARNING in docstring):

Tool Cost driver
policy_engine_create Provisions a policy engine (infrastructure)
policy_create Invokes validation pipeline, provisions policy
policy_update Re-invokes validation pipeline
policy_generation_start Foundation-model invocation — most expensive

Destructive (irreversible):

  • policy_engine_delete — requires zero associated policies first
  • policy_delete

Read-only (no cost):

All *_get, *_list, and get_policy_guide — 8 tools total,
including the guide.

How the guardrails are enforced

  1. Every billable tool has COST WARNING: prefixed in its docstring,
    placed prominently so the LLM sees it before deciding to call.
    policy_generation_start explicitly calls out "typically the most
    expensive Policy operation per call."
  2. The __init__.py module docstring groups all 15 tools by risk tier.
  3. The same grouping appears in the get_policy_guide output under
    "Tool Cost Tiers."
  4. Operators can opt out entirely via
    AGENTCORE_DISABLE_TOOLS=policy, and the integration test suite
    includes a test_list_tools_policy_disabled test asserting this
    works.

Known limitation

_is_service_enabled('policy') is on by default, matching all other
primitives. There is no per-tool gating today (e.g., "disable policy
generation but keep read-only"). If we want finer-grained gating
after this lands, it should be a cross-cutting change applied to all
primitives, not a Policy-specific bolt-on.


Architecture

awslabs/amazon_bedrock_agentcore_mcp_server/tools/policy/
├── __init__.py          # register_policy_tools(mcp) entry point
├── policy_client.py     # Cached bedrock-agentcore-control client
├── models.py            # 10 Pydantic response models
├── error_handler.py     # ClientError → ErrorResponse mapping
├── engines.py           # PolicyEngineTools (5 tools)
├── policies.py          # PolicyTools (5 tools)
├── generations.py       # PolicyGenerationTools (4 tools)
└── guide.py             # GuideTools (1 tool)

Design decisions

  • Single client, not two. All Policy APIs are control plane, so
    we use one cached bedrock-agentcore-control client via
    get_policy_client(). User-agent is build_user_agent('policy')
    (no -control suffix, matching the single-client pattern used by
    browser and code-interpreter).
  • Guide returns a Pydantic model. get_policy_guide returns
    PolicyGuideResponse(guide=...) rather than dict[str, str]
    every tool in the sub-package returns a BaseModel, including the
    guide.
  • No clear_clients() or other cleanup. boto3 clients don't hold
    open connections; there's nothing to shut down. The sub-package
    does not hook into server_lifespan.
  • No PII in logs. Logger calls only include resource IDs
    (policy_engine_id, policy_id, policy_generation_id), operation
    names, and counts — never user-provided Cedar statements,
    natural-language generation inputs, or descriptions.

Files Changed

New — sub-package (8 files)

src/amazon-bedrock-agentcore-mcp-server/awslabs/amazon_bedrock_agentcore_mcp_server/tools/policy/
  __init__.py
  policy_client.py
  models.py
  error_handler.py
  engines.py
  policies.py
  generations.py
  guide.py

New — tests (9 files)

src/amazon-bedrock-agentcore-mcp-server/tests/policy/
  __init__.py
  conftest.py
  test_unit_policy_client.py
  test_unit_engines.py
  test_unit_policies.py
  test_unit_generations.py
  test_unit_error_handler.py
  test_unit_init.py
  test_unit_guide.py

Modified (3 files)

  • server.py — adds the _is_service_enabled('policy') block
    with import-error fallback. Tool count logged as 15.
  • tests/test_tools.py — adds TestPolicyTool class exercising
    the guide tool and its Pydantic response. Existing TestMemoryTool
    and TestGatewayTool are unchanged.
  • tests/browser/test_integ_mcp_protocol.py — adds POLICY_TOOLS
    set (15 tools), registers policy in _build_server(), adds two
    schema tests (test_policy_tools_require_policy_engine_id,
    test_policy_engine_create_has_optional_params), a discovery opt-out
    test (test_list_tools_policy_disabled), and one protocol
    invocation test (test_policy_guide_invocation). Existing tests
    updated to include POLICY_TOOLS in the default-config expectation.

Checklist

If your change doesn't seem to apply, please leave them unchecked.

  • [x ] I have reviewed the contributing guidelines
  • [x ] I have performed a self-review of this change
  • [x ] Changes have been tested
  • [x ] Changes are documented

Is this a breaking change? N

RFC issue number:

Checklist:

  • [ x] Migration process documented
  • [x ] Implement warnings (if it can live side by side)

Acknowledgment

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the project license.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 20, 2026

Codecov Report

❌ Patch coverage is 98.46154% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.52%. Comparing base (758e85b) to head (efae4d4).

Files with missing lines Patch % Lines
...labs/amazon_bedrock_agentcore_mcp_server/server.py 44.44% 4 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3193      +/-   ##
==========================================
+ Coverage   92.49%   92.52%   +0.02%     
==========================================
  Files         859      867       +8     
  Lines       68021    68346     +325     
  Branches    10900    10926      +26     
==========================================
+ Hits        62919    63239     +320     
- Misses       3080     3084       +4     
- Partials     2022     2023       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant