Skip to content

feat(setup): send the agent's model calls to a LaunchDarkly Bedrock relay (7/7) - #930

Open
atornsii wants to merge 3 commits into
atorns/agent-6-run-fixesfrom
atorns/agent-7-bedrock-routing
Open

atornsii wants to merge 3 commits into
atorns/agent-6-run-fixesfrom
atorns/agent-7-bedrock-routing

Conversation

@atornsii

@atornsii atornsii commented Oct 20, 2026 •

Copy link
Copy Markdown

This sends the setup agent's model calls to a LaunchDarkly Bedrock relay in gonfalon. LaunchDarkly pays for the calls, and no model key is on the user's machine. It is the seventh agent PR, on top of #899.

How it works

  1. ldcli reads the ldcli-setup-agent config before it starts OpenCode, because OpenCode reads its configuration only once. The config must be on and must name a Bedrock model, such as Bedrock.anthropic.claude-sonnet-4-6. If it does not, setup stops with an error. It does not use the user's own OpenCode provider.
  2. The OpenCode configuration turns on only amazon-bedrock, with region: us-east-1 and endpoint on the loopback proxy. It sets model and small_model to the config's model, because OpenCode's default small model is a global inference profile (global.anthropic.claude-haiku-5-5).
  3. OpenCode gets AWS_BEARER_TOKEN_BEDROCK=ldcli-placeholder, which takes priority over every AWS credential. The user's own AWS_ variables do not reach OpenCode.
  4. The proxy gives OpenCode a second secret path. That path accepts only POST /model/..., and it reaches only /internal/ldcli-setup-agent/bedrock on gonfalon. OpenCode cannot reach the SDK routes. The proxy removes the bearer placeholder and adds LD-CLI-Token.

OpenCode adds the US inference profile prefix itself, so the request is POST /model/us.anthropic.claude-sonnet-4-6/converse-stream. The gonfalon side, which checks the token and signs the call for Bedrock, is launchdarkly/gonfalon#75426.

Testing

  • A test runs the real OpenCode 1.19.3, in the macOS sandbox, against a fake relay through the proxy. Every model call reaches /internal/ldcli-setup-agent/bedrock/model/us.anthropic.claude-sonnet-4-6/converse-stream with the token header and without the bearer placeholder. The test skips if OpenCode is not installed.
  • Unit tests cover the OpenCode configuration, the proxy route and its refusals, the removal of AWS_ variables, and the refusal of a config that is off or that names another provider.
  • A manual test with the user's real OpenCode login file showed that only amazon-bedrock is on.

Stack

This is the seventh agent PR. Merge it after #894 to #899, which come after #877 (Go 1.26).

🤖 Generated with Claude Code


Note

Overview
Routes logged-in setup agent model traffic through LaunchDarkly-managed Amazon Bedrock on gonfalon instead of the user’s OpenCode providers. Setup now requires an enabled ldcli-setup-agent AI Config with a Bedrock model before OpenCode starts; there is no fallback to the user’s own API keys or providers.

OpenCode config (openCodeConfig) optionally pins amazon-bedrock as the only provider, sets model/small_model, and points Bedrock at a loopback proxy endpoint with us-east-1. startServer can inject AWS_BEARER_TOKEN_BEDROCK (placeholder) and strips AWS_* from the child environment so OpenCode never uses local AWS credentials.

The relay proxy gains a second secret bedrockURL that forwards only validated POST /model/{id}/{op} requests to /internal/ldcli-setup-agent/bedrock, strips the placeholder Authorization bearer, and still attaches LD-CLI-Token. AIConfigSource.managedModel resolves the Bedrock model and proxy endpoint using the same runCtx as the AI SDK stream for consistent targeting.

Tests cover managed OpenCode JSON, proxy routing/refusals, env stripping, managed-model errors, and an optional real OpenCode sandbox test.

Reviewed by Cursor Bugbot for commit e3c6c40. Bugbot is set up for automated code reviews on this repo. Configure here.

…elay

For a logged-in user, OpenCode now calls only the model in the setup agent config, through the loopback proxy and the gonfalon model relay at /internal/ldcli-setup-agent/bedrock. No model key is on the user's machine.

The OpenCode configuration turns on only the amazon-bedrock provider, points it at the proxy, and uses the config's model for title generation too. OpenCode gets a placeholder bearer token, and the user's AWS variables do not reach it. The proxy gives OpenCode its own secret path, which reaches only POST /model/... on the model relay, and it replaces the placeholder with the access token.

ldcli now reads the config before it starts OpenCode. If the config is off or does not name a Bedrock model, setup stops and does not use the user's own provider.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@atornsii
atornsii added this pull request to stack #902 October 20, 2026 21:55
@atornsii
atornsii marked this pull request as ready for review October 20, 2026 21:56
@atornsii
atornsii requested a review from a team as a code owner October 20, 2026 21:56
@atornsii
atornsii requested review from davidbrackbill and removed request for a team October 20, 2026 21:56
devin-ai-integration[bot]

This comment was marked as resolved.

cursor[bot]

This comment was marked as resolved.

atornsii and others added 2 commits October 20, 2026 15:12
managedModel and the AI SDK stream now use the same context. The context key is random, so with percentage targeting two contexts could pick different variations, and OpenCode could get a model that it did not enable.

The proxy now accepts only /model/{modelId}/{operation} on the model path, with no empty, . or .. segment. Before, a path such as /model/../../sdk/... could leave the model relay with the user's token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…outing

# Conflicts:
#	internal/setup/agent/opencode_config.go
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