ReqManagedAgents.Providers.BedrockAgentCore.Client (ReqManagedAgents v0.13.3)

Copy Markdown View Source

SigV4-signed REST client for AWS AgentCore (bedrock-agentcore). Covers the control-plane harness lifecycle (create_harness/get_harness/get_harness_endpoint/delete_harness), the AgentCore Identity token-vault (create_api_key_credential_provider), and the data-plane invoke_harness (returns a decoded vnd.amazon.eventstream).

Infra-agnostic: it knows AgentCore's model-config surface, nothing about what sits behind a liteLlmModelConfig.apiBase. Build with new/1; pass as the first arg to every call. Transport is injectable via :req_options for tests.

The invoke data plane streams incrementally: receive_timeout on this struct governs control-plane calls only, while invoke_harness/2 uses the per-invoke :idle_timeout (default 300_000 ms) as an inter-chunk liveness guard — a healthy turn may run arbitrarily long; only silence fails it.

Summary

Functions

Worst-case number of HTTP attempts one control-plane call makes, by method.

GetHarnessEndpoint (control plane). Returns the decoded body %{"endpoint" => %{"endpointName", "status", "arn", "liveVersion", ...}}.

Data-plane InvokeAgentRuntimeCommand — run a shell command inside the session's microVM (no model loop, no token cost) and collect its streamed output.

Data-plane InvokeHarness. Sends messages with harnessArn in the query string and the required X-Amzn-Bedrock-AgentCore-Runtime-Session-Id header. Returns the decoded event-stream maps. Resume is just another call with the resume messages (the profile assembles them).

One ListHarnesses page (control plane). Returns the decoded body %{"harnesses" => [%{"harnessName", "harnessId", "arn", "status", ...}], "nextToken" => ...}. Pass :next_token to continue and :max_results (1..100) to set the page size. Tokens are opaque; the caller owns traversal and response validation.

Types

t()

@type t() :: %ReqManagedAgents.Providers.BedrockAgentCore.Client{
  base_url: String.t(),
  control_base_url: String.t(),
  credentials: ReqManagedAgents.AWS.SigV4.creds(),
  receive_timeout: timeout(),
  req_options: keyword(),
  service: String.t()
}

Functions

control_plane_attempts(method)

@spec control_plane_attempts(:get | :post | :delete) :: pos_integer()

Worst-case number of HTTP attempts one control-plane call makes, by method.

receive_timeout applies per attempt, so a caller bounding a call by a wall-clock budget has to divide by this — otherwise a hung request spends the whole budget once per attempt.

:get and :delete pass retry: :transient and so make the initial request plus 2 retries. :post (CreateHarness, credential providers) passes no retry option and inherits Req's :safe_transient policy, which does not retry a non-idempotent method — one attempt.

The count covers attempts only. Req also sleeps between them (exponential backoff, or a Retry-After header), and Finch's connect timeout sits outside receive_timeout — so a budget divided by this bounds the receive phase, not the total wall-clock of a retried call.

create_api_key_credential_provider(c, map)

@spec create_api_key_credential_provider(
  t() | ReqManagedAgents.AgentCore.Client.t(),
  map()
) ::
  {:ok, map()} | {:error, term()}

create_harness(c, spec)

@spec create_harness(
  t() | ReqManagedAgents.AgentCore.Client.t(),
  ReqManagedAgents.Providers.BedrockAgentCore.HarnessSpec.t() | map()
) :: {:ok, map()} | {:error, term()}

delete_harness(c, id)

@spec delete_harness(t() | ReqManagedAgents.AgentCore.Client.t(), String.t()) ::
  {:ok, map()} | {:error, term()}

get_harness(c, id)

@spec get_harness(t() | ReqManagedAgents.AgentCore.Client.t(), String.t()) ::
  {:ok, map()} | {:error, term()}

get_harness_endpoint(c, harness_id, endpoint_name)

@spec get_harness_endpoint(
  t() | ReqManagedAgents.AgentCore.Client.t(),
  String.t(),
  String.t()
) ::
  {:ok, map()} | {:error, term()}

GetHarnessEndpoint (control plane). Returns the decoded body %{"endpoint" => %{"endpointName", "status", "arn", "liveVersion", ...}}.

A harness and each of its endpoints carry separate statuses and reach READY at different times, so a READY harness is not yet invokable. The data plane's qualifier defaults to the DEFAULT endpoint, which makes that endpoint the one a provision has to wait on.

invoke_agent_runtime_command(c, inv)

@spec invoke_agent_runtime_command(t() | ReqManagedAgents.AgentCore.Client.t(), map()) ::
  {:ok, ReqManagedAgents.Providers.BedrockAgentCore.CommandResult.t()}
  | {:error, term()}

Data-plane InvokeAgentRuntimeCommand — run a shell command inside the session's microVM (no model loop, no token cost) and collect its streamed output.

inv requires :agent_runtime_arn (the harness/runtime ARN — it rides the URI path), :runtime_session_id, and :command. Optional: :timeout_seconds (server-side cap, service default 300, max 3600), :idle_timeout (inter-chunk liveness guard, default 300_000 ms), :on_output (fn (:stdout | :stderr, chunk) called per delta, in order), :qualifier (endpoint name).

Returns {:ok, %ReqManagedAgents.Providers.BedrockAgentCore.CommandResult{}} — a non-zero exit_code is a RESULT, not an error. Transport/stream failures return {:error, term()}.

invoke_harness(c, inv)

@spec invoke_harness(t() | ReqManagedAgents.AgentCore.Client.t(), map()) ::
  {:ok, [map()]} | {:error, term()}

Data-plane InvokeHarness. Sends messages with harnessArn in the query string and the required X-Amzn-Bedrock-AgentCore-Runtime-Session-Id header. Returns the decoded event-stream maps. Resume is just another call with the resume messages (the profile assembles them).

Note: AWS requires runtimeSessionId to be at least 33 characters long (pattern [a-zA-Z0-9][a-zA-Z0-9-_]*, max 100). The client passes it through as-is — the caller is responsible for supplying a conforming value.

list_harnesses(c, opts \\ [])

@spec list_harnesses(
  t() | ReqManagedAgents.AgentCore.Client.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}

One ListHarnesses page (control plane). Returns the decoded body %{"harnesses" => [%{"harnessName", "harnessId", "arn", "status", ...}], "nextToken" => ...}. Pass :next_token to continue and :max_results (1..100) to set the page size. Tokens are opaque; the caller owns traversal and response validation.

new(opts \\ [])

@spec new(keyword()) :: t()