Skip to content

feat(provider): native AWS Bedrock (Converse API, hand-rolled SigV4) - #143

Merged
prashar32 merged 1 commit into
mainfrom
feat/bedrock-provider
Jun 17, 2026
Merged

feat(provider): native AWS Bedrock (Converse API, hand-rolled SigV4)#143
prashar32 merged 1 commit into
mainfrom
feat/bedrock-provider

Conversation

@prashar32

Copy link
Copy Markdown
Owner

Implements native AWS Bedrock (#24), replacing the stub. Run Bedrock-hosted models through RiskKernel with the same budgets / approvals / audit / OTel as any other provider.

export AWS_ACCESS_KEY_ID=...  AWS_SECRET_ACCESS_KEY=...  AWS_REGION=us-east-1
export RISKKERNEL_DEFAULT_PROVIDER=bedrock
riskkernel serve
# then call with a Bedrock model id, e.g. anthropic.claude-3-5-sonnet-20240620-v1:0

Approach — minimal deps

  • Built against the Bedrock Runtime Converse API (unified across models, returns token usage).
  • Signed with a hand-rolled AWS SigV4 signer — no aws-sdk-go-v2 dependency (it pulls dozens of modules; this is ~120 lines). Keeps the dependency graph minimal per the project's posture.
  • The signer is verified against AWS's published SigV4 get-vanilla known-answer vector — I independently reproduced that vector's signature with openssl before encoding it as the test oracle, so the test isn't circular.
  • Bedrock model ids contain : (e.g. …-v1:0); the path is AWS-encoded (%3A) for both the wire request and the signed canonical URI so they match (verified Go's Path/RawPath round-trip).

Wiring

  • Registered only when AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY are set; with RISKKERNEL_DEFAULT_PROVIDER=bedrock and no creds, the daemon refuses to start with a clear error.
  • RISKKERNEL_BEDROCK_BASE_URL overrides the endpoint (VPC/PrivateLink or a mock). AWS_SESSION_TOKEN supported for STS temp creds. Creds from env only, never stored/logged.
  • Routing: Bedrock model ids fall to the default provider (they don't match the claude-*/gpt-* prefixes), which is why you set RISKKERNEL_DEFAULT_PROVIDER=bedrock — documented.
  • Removes the old stub + the now-unused ErrNotImplemented; no stubs remain.

Honesty

Long-tail Bedrock model ids meter priced:false (cost $0, token budget only) until a RISKKERNEL_PRICING_FILE rate is added — same caveat as the LiteLLM path, documented in docs/PROVIDERS.md.

Tests / verification

  • SigV4 known-answer vector; AWS URI path encoding; Bedrock provider against a mock (request shape, well-formed …/bedrock/aws4_request auth header, content-type;host;x-amz-date signed headers, session token in signed headers, response parsing, API-error / missing-creds / missing-region / context-cancel).
  • go test -race ./... green; go vet / gofmt clean.
  • End-to-end: riskkernel chat --provider bedrock against a mock that validates the SigV4 Authorization header returned signed-ok and parsed usage — proving the env→config→register→sign→call path.

Docs: native AWS Bedrock section in docs/PROVIDERS.md; README + ROADMAP updated (Bedrock moves to Shipped).

Closes #24

Implement Bedrock natively against the Bedrock Runtime Converse API, replacing
the stub. Run Bedrock-hosted models through RiskKernel with the same budgets,
approvals, audit, and OTel as any other provider — set the standard AWS env vars
(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, optional AWS_SESSION_TOKEN, AWS_REGION)
and RISKKERNEL_DEFAULT_PROVIDER=bedrock, then call with a Bedrock model id.

Requests are signed with a hand-rolled AWS SigV4 signer — no AWS SDK dependency,
keeping the dependency graph minimal. The signer is verified against AWS's
published SigV4 'get-vanilla' known-answer test vector. Model ids contain ':'
(e.g. ...-v1:0), so the path is AWS-encoded (%3A) for both the wire request and
the signed canonical URI so they match.

Bedrock is registered only when AWS credentials are present (the daemon refuses
to start with a clear error if RISKKERNEL_DEFAULT_PROVIDER=bedrock but no creds);
RISKKERNEL_BEDROCK_BASE_URL overrides the endpoint for a VPC/PrivateLink setup.
Credentials come from the environment, never stored or logged.

Removes the old stub provider and the now-unused ErrNotImplemented; updates the
provider/stream package docs (no stubs remain — Anthropic, OpenAI, Ollama, and
Bedrock are all native).

Tests: the SigV4 known-answer vector, the AWS URI path encoding, and the Bedrock
provider against a mock (request shape + well-formed SigV4 auth header + session
token in signed headers + response parsing + error/missing-creds/missing-region/
context-cancel paths). Verified end-to-end: 'riskkernel chat --provider bedrock'
against a mock that validates the SigV4 Authorization header.

Docs: docs/PROVIDERS.md gains a native AWS Bedrock section (routing, the pricing
caveat); README + ROADMAP updated.
@prashar32
prashar32 merged commit 1d171c1 into main Jun 17, 2026
5 checks passed
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.

Native AWS Bedrock provider

1 participant