anthropics / anthropics/claude-agent-sdk-python

[FEATURE] Native Bedrock Guardrail body wrapping for InvokeModel / InvokeModelWithResponseStream

未關閉
#999 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
enhancement
主要語言
Python
星號
8.1k
分支
1.3k
平均合併
2 天 31 分鐘
30 天內合併 PR
1

描述

## Summary

When using `claude-agent-sdk` with Amazon Bedrock and a Bedrock Guardrail
attached via the `X-Amzn-Bedrock-GuardrailIdentifier` /
`X-Amzn-Bedrock-GuardrailVersion` headers (e.g. injected through
`ANTHROPIC_CUSTOM_HEADERS`), every `InvokeModel` /
`InvokeModelWithResponseStream` call fails closed with:

HTTP 400 Guardrail was enabled but input is in incorrect format.

The model is never invoked, the guardrail never evaluates, no usage is
billed beyond the round-trip, and no `guardrailTrace` event is produced —
so guardrails can be neither **enforced** nor **observed** while routing
through this SDK against Bedrock.

Reproduced on `claude-agent-sdk==0.2.87` + `us.anthropic.claude-opus-4-7`
on Bedrock `us-east-1`, both single-agent and multi-agent (sub-agent /
A2A) configurations.

## Why it fails

Bedrock Guardrail enforcement on the InvokeModel path requires **two
coordinated changes** per request:

1. **Headers** — `X-Amzn-Bedrock-GuardrailIdentifier`,
`X-Amzn-Bedrock-GuardrailVersion`, optional
`X-Amzn-Bedrock-Trace`. The SDK forwards these correctly.

2. **Body** — when the headers are present, Bedrock requires:
- a top-level `amazon-bedrock-guardrailConfig` object
(e.g. `{\"streamProcessingMode\": \"sync\"}`), and
- natural-language text segments in `messages[]` and the system
prompt wrapped in
`>...`
markers so the engine knows which spans to evaluate.
Tool-use / tool-result blocks must NOT be wrapped.

The SDK currently emits Anthropic Messages-shaped bodies on the
Bedrock path with neither of these, so Bedrock fails closed.

Reference: AWS Bedrock Guardrails — *Use a guardrail with the
InvokeModel API* (the `guardContent` and `guardrailConfig` sections).

## Requested behavior

When \`ClaudeAgentOptions\` is configured for Bedrock and the runtime
detects guardrail headers (or via an explicit option, e.g.
\`bedrock_guardrail={\"id\": \"...\", \"version\": \"DRAFT\"}\`), the SDK should:

- Inject \`amazon-bedrock-guardrailConfig\` into the outgoing body.
- Wrap text content blocks in \`messages[]\` and the system prompt with
\`guardContent\` markers; leave \`tool_use\` / \`tool_result\` blocks
untouched.
- Pass through \`guardrailTrace\` / intervention metadata on the
response side so callers can attribute guardrail actions to a turn.

Equivalent support is already needed on
\`InvokeModelWithResponseStream\` for the streaming code path.

## Why this matters

Without native support, integrators have two choices, both bad:

1. **Local botocore hook** that monkey-patches the outgoing body —
fragile, will silently double-wrap once the SDK adds real support
unless a feature flag is plumbed.
2. **\`ApplyGuardrail\` sidecar calls** — possible for *observability*
but does not enforce; adds 1–2 extra round-trips per turn.

Native support lets every \`claude-agent-sdk\` user pick up Bedrock
Guardrail enforcement and the corresponding \`guardrailTrace\`
observability with a single config option, the same way Bedrock
Guardrail headers already work today.

## Related

- Bedrock Converse API handles this natively; the InvokeModel path
does not. Migrating the SDK's Bedrock transport to Converse would
also resolve this (and prompt-caching #626) but is a larger change.

## Environment

- \`claude-agent-sdk==0.2.87\`
- AWS Bedrock \`us-east-1\`
- \`us.anthropic.claude-opus-4-7\`
- Reproduced on AWS Bedrock AgentCore Runtime; same body-shape issue
applies to any caller that adds guardrail headers.

貢獻指南

這個儲存庫沒有索引到貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。