# `ReqManagedAgents.Providers.BedrockAgentCore`
[🔗](https://github.com/cash-mckeeman/req_managed_agents/blob/v0.13.0/req_managed_agents/lib/req_managed_agents/providers/bedrock_agent_core.ex#L1)

`ReqManagedAgents.Provider` for the Bedrock AgentCore backend — `:request_response` mode.
Each turn is one `InvokeHarness` call; resume re-sends the assistant `toolUse` + user
`toolResult` delta (the harness does not persist the uncommitted tool-use turn). Composes
the provider's `Client` and `Converse` modules. Decoded events are additionally
delivered live to the session as `{:provider_event, ev}` messages while a turn streams.
`provision/2`'s `opts[:environment]` carries an `Environment.Spec` (or a map coerced via
`Environment.Spec.new/1`, or `nil`). Its opaque `config` is handed to CreateHarness's
`environment` field VERBATIM — no per-key indexing, symmetric with how
`ClaudeManagedAgents` passes `config` straight to its wire body (filesystem mounts, custom
containers, env vars, all opaque and never interpreted by this library). Environment is
first-class (#70/#72): it reaches this provider only via `opts[:environment]`, never the
spec, and its digest is folded into the harness name so different environments never
collide on a name.

# `build_spec`

```elixir
@spec build_spec(
  map(),
  keyword()
) ::
  {:ok, ReqManagedAgents.Providers.BedrockAgentCore.HarnessSpec.t()}
  | {:error, term()}
```

Assembles the AgentCore harness-creation spec from an `Agent.Spec`-shaped
`spec` map and provisioning `opts`. Validates `opts[:execution_role_arn]`
BEFORE it ever reaches `CreateHarness` — a blank/missing value used to pass
straight through (`Keyword.fetch!/2` only guards the key being absent, not a
present-but-blank value) and surface as a cryptic AWS `HTTP 400 "Value null
at 'executionRoleArn'"` (GitHub #64).

# `provision`

Provisions the harness for `spec`, waiting for it **and the endpoint an invoke
will reach** to become READY.

The two carry separate statuses and reach READY at different times, so a wait
on the harness alone can return a handle that is not yet invokable. The
endpoint is `opts[:endpoint_name]`, defaulting to `DEFAULT` —
the endpoint `InvokeHarness` uses when no `qualifier` is given. `open/2` takes
the same option and sends it as that `qualifier`, so gating a provision on a
non-default endpoint and then invoking it are the one option, not two.

`opts[:timeout]` (ms) is the budget for the whole call, converted once here into
a monotonic deadline shared by every wait and by every request they make — a
provision that cannot finish returns a named error tuple strictly inside it
rather than running past the deadline of whatever it runs under. The one
exception is the best-effort rollback of a harness this call created, which runs
after the budget is spent and so carries a small fixed budget of its own.

`opts[:endpoint_name]` is validated against the service's own
`[a-zA-Z][a-zA-Z0-9_]{0,47}` before anything is created — an unresolvable name
returns `{:error, {:invalid_opts, :endpoint_name}}` rather than costing a
harness the wait would then roll back.

The legacy `:ready_poll_ms` / `:ready_max_polls` pair is still accepted; see
`ReqManagedAgents.Providers.BedrockAgentCore.WaitBudget` for how the two shapes
relate.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
