Repository navigation
Conversation
added 7 commits
September 19, 2026 22:12
Wire the deployed buyer crew to a deployed seller by ARN, and close the remaining gaps between the ECS and AgentCore runtimes for the buyer. Buyer -> seller integration (AgentCoreSellerProxy): - New OpenDirect-shaped proxy backed by bedrock-agentcore:InvokeAgentRuntime against the seller MCP runtime. Issues MCP tools/call over the Streamable-HTTP transport with the required Accept/contentType/protocol headers and the initialize -> notifications/initialized handshake, threads Mcp-Session-Id for microVM stickiness, and parses SSE-framed results. Maps structured seller products to OpenDirect via the shared wire mapper. - crew_tools: use the proxy for the ARN seller case (was a localhost stub). - New CFN stack infra/aws/agentcore/auth-agentcore.yaml: CFN-owned buyer runtime execution role with a scoped runtime/a4a_aamp_seller_* invoke wildcard, restricted to same-account / trusted cross-account (cross-org uses the gateway + CUSTOM_JWT path). deploy.sh deploys it and passes the role via `agentcore configure --execution-role`. AgentCore deploy parity fixes (deploy.sh / requirements.txt): - Add PYTHONPATH=/app/src so ad_buyer is importable in the runtime image. - Default the LLM + memory models to Bedrock Claude Sonnet (was nova-pro / nova-lite), matching settings.py and the Bedrock migration. - Pin crewai>=1.14.4,<2.0.0 (was ==1.10.1) to match pyproject.toml; the Bedrock fix patch and DealBookingFlow rely on CrewAI >=1.14. Tests: - Unit: tests/unit/agentcore/test_agentcore_seller_proxy.py (11) covering MCP result parsing/mapping, required MCP headers, the initialize handshake ordering + initialize-once, and SSE-framed response parsing. - Integration: tests/integration/agentcore/test_runtime.py adds TestBuyerSellerIntegration (deployed buyer->seller loop asserts real seller inv-* inventory via CloudWatch); raise invoke timeouts for the real crew runtime on Claude. - Fix test_agent_hierarchy temperature assertions to be model-aware: build_llm correctly omits temperature for Claude families that reject it (e.g. claude-sonnet-5), so assert the tuned value only when the configured model accepts temperature. All three buyer runtime integration tests + the buyer->seller loop verified live (real inv-* inventory reaches the buyer through the proxy).
…point
Route CrewAI's LLM calls through Amazon Bedrock's Anthropic-compatible
(Messages) endpoint instead of the Converse provider, and retire Amazon
Nova as the default model.
Motivation
----------
The Converse path required a monkey-patch (patches/crewai_bedrock_fix.py)
to strip orphaned toolUse/toolResult blocks. Bedrock's Anthropic Messages
endpoint (bedrock-runtime .../anthropic) assembles tool turns itself, so
that class of ValidationException does not arise. Nova Pro is being
deprecated; current-generation Claude tiers (Sonnet 5, Haiku 4.5) are
served on the Messages API.
Changes
-------
- llm.build_llm: add an Anthropic-Messages-compatible base_url branch,
selected via ANTHROPIC_COMPATIBLE_LLM_API_BASE_URL. Takes precedence
over the OpenAI-compatible branch so Claude is never misrouted to the
OpenAI client (Claude is not served on Bedrock's Chat Completions).
- settings: add anthropic_compatible_llm_api_{base_url,key}; default
model anthropic/claude-sonnet-4-5 -> anthropic/claude-sonnet-5.
- http_main: apply the Converse sanitizer only on the legacy Converse
path (bedrock/ model + no Messages base URL); on the Messages path
apply the new strict-strip patch instead.
- patches/crewai_bedrock_anthropic_fix.py (new): strip the tool "strict"
field that CrewAI (>=1.15) emits, which Bedrock's Anthropic endpoint
rejects (tools.0.custom.strict: Extra inputs are not permitted). Scoped
to Bedrock base URLs only; real Anthropic is unchanged.
- agentcore memory patch + crew_tools fallback: Nova -> Claude Haiku 4.5.
- infra/aws/agentcore/deploy.sh: source .env; default to Sonnet 5 /
Haiku 4.5 via the Messages endpoint; set PYTHONPATH=/app/src so the
package resolves under the toolkit's module entrypoint.
- infra/aws/agentcore/requirements.txt: align crewai with pyproject
(>=1.14.4) and add iab-agentic-primitives via a git-free archive URL
(the build image has no git binary).
- .env.example: document the Messages-endpoint configuration.
Compatibility
-------------
Backward-compatible: the Converse provider and its patch remain available
for anyone using a bedrock/ Converse model. Removing the Converse patch
entirely is deferred to a follow-up change.
Testing
-------
- Unit + mocked integration: 3462 passed.
- Live AgentCore integration (deployed dev runtime): 4/4 passed
(chat + three crew-plan invocations).
OpenAI's newer models (GPT-5.x, o1/o3/o4 reasoning models) reject the legacy max_tokens parameter on Bedrock's OpenAI-compatible endpoint with "400 invalid_request_error: Unsupported parameter: 'max_tokens' is not supported with this model." They take max_completion_tokens instead. build_llm now routes the token cap to max_completion_tokens for those model families (matched as substrings so Bedrock inference-profile ids like us.openai.gpt-5.6-sol and raw ids like gpt-5/o1 are covered) and keeps max_tokens for everything else (gpt-4o, Claude, Nova, ...). Surfaced while running the buyer crew against a Bedrock OpenAI (GPT-5.6) model to validate the "any model on Bedrock" path; with the fix the GPT crew invoke completes cleanly. Adds regression tests for the helper and the build_llm parameter routing.
Mirrors the seller fix. The crew path runs Claude on Bedrock's Anthropic Messages endpoint (x-api-key bearer token, not SigV4), so a token baked into --env expires within hours and 403s every crew call. - ad_buyer.llm.bedrock_token: mint a fresh bearer token from the runtime's own execution role at startup (authoritative on a Bedrock base URL so a stale baked key never shadows it), with a reactive refresh path; a non-Bedrock base URL still respects an operator-supplied key. Never crashes startup. - Wired into the http entrypoint at module load. - auth-agentcore.yaml: the CFN-owned buyer runtime role now grants bedrock:CallWithBearerToken (the bearer-token Messages path) alongside InvokeModel; deploy.sh stops baking an empty/stale key. - Adds aws-bedrock-token-generator to requirements. Live-verified: buyer crew campaign-planning integration tests pass under real Bedrock calls with no expired-token or permission errors.
…/refresh) For the AWS Bedrock AgentCore deployment path: when the buyer discovers a seller runtime fronted by a CUSTOM_JWT authorizer that advertises an OAuth2 token endpoint + scope in its AAMP registry 'authentication' object, it must present Authorization: Bearer <JWT>. OAuthTokenProvider mints that JWT via the client_credentials grant. - Reads token endpoint + scope from the DISCOVERED record; holds the buyer's own client_id/secret from settings (never from the registry, never logged). - POSTs grant_type=client_credentials (HTTP Basic), caches keyed by (token_endpoint, scope), refreshes proactively before expiry and reactively via invalidate() on a 401. Same helper serves a BYO-IdP token endpoint. - Additive: the legacy per-seller API-key path (AuthMiddleware) and the arn: AgentCore SigV4 proxy path are unchanged — OAuth applies only to a discovered seller that advertises an issuer (the cross-org case those paths can't cover). 10 unit tests (mint, cache, proactive/reactive refresh, per-scope keys, unconfigured/error handling, secret never logged).
…_JWT) When the seller runtime enforces a CUSTOM_JWT authorizer (AWS Bedrock AgentCore deployment path), SigV4/boto3 InvokeAgentRuntime is rejected — per the AgentCore docs, an OAuth runtime must be reached via a raw HTTPS request to the invocations URL with a Bearer token. This wires that path for the buyer's catalog/planning calls (MCP surface). - transport_selector.select_seller_client(): arn without OAuth -> SigV4 proxy; arn/https WITH advertised OAuth -> JWT path; https without OAuth -> plain MCP. agentcore_invocations_url() builds the verified HTTPS URL from an ARN (:->%3A, /->%2F, /invocations?qualifier=DEFAULT). - AgentCoreSellerProxy gains a JWT transport mode: same OpenDirect surface DealBookingFlow needs, but frames MCP over an httpx POST with a Bearer JWT (from OAuthTokenProvider), re-minting once on a 401. - IABMCPClient: optional OAuth bearer + no longer forces /mcp/sse on a full AgentCore invocations URL. - crew_tools routes through the selector when the seller advertises OAuth (SELLER_TOKEN_ENDPOINT); deploy.sh forwards the seller token endpoint/scope, the buyer's own client creds, and SELLER_MCP_RUNTIME_ARN (each only when set). Live-verified: the buyer crew reaches the seller's real inv-* catalog through the JWT/HTTPS MCP call to the CUSTOM_JWT seller MCP runtime (no 401/403). 14 unit tests for the selector; buyer unit suite green.
Add tests/integration/test_registry_roundtrip.py (task 7.3): seed the library registry double, discover the seller via AampRegistryClient over an httpx ASGITransport (in-process, no hosted registry), and assert the transport selector routes an OAuth-advertising https endpoint to the JWT client and an arn: (no OAuth) to the SigV4 proxy. Also covers the fail-closed contract (OAuth advertised + no buyer creds -> RuntimeError). 3 passed.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cross-org auth for the buyer calling the seller: an OAuth client_credentials token
provider (mint/cache/refresh), a JWT/HTTPS MCP transport with a registry-driven
transport selector, and a register→discover→connect round-trip test (no network).
Changes
auth/oauth_token_provider.py(fully-qualified scope, pool-domain/oauth2/token); runtime Bedrock token minted from the execution role.registry/transport_selector.pypicks JWT/HTTPS vs proxy;clients/mcp_client.pycross-org path; proxy + crew_tools wiring.tests/integration/test_registry_roundtrip.pyregister→discover→connect.Testing
New units green:
test_oauth_token_provider.py,test_transport_selector.py,test_bedrock_token.py; registry round-trip integration passes.Base:
buyer-mr1-transport(stacked).