Connect to runtime sessions through a session endpoint
With session endpoints, you can connect to application servers running inside an Amazon Bedrock AgentCore Runtime session. A session endpoint is an authenticated HTTPS URL that addresses one runtime session. Use it to:
-
View a web preview.
-
Call custom HTTP routes.
-
Stream responses.
-
Call a gRPC service.
-
Open a WebSocket connection.
Configure allowedPorts to choose which container ports you can reach. Connect through the session endpoint URL that Runtime returns.
For each request, Runtime checks your credentials and access to the requested port. It forwards allowed requests to your server and relays the response.
To customize InvokeAgentRuntime without session endpoints, see Configure your agent’s serving port and invocation path.
Note
Session endpoints and custom invocation settings support microVM runtimes. They don’t support Instances with capacity providers. Session endpoints use public HTTPS ingress. AWS PrivateLink ingress isn’t supported.
Session endpoints and runtime endpoints
A session endpoint is different from a runtime endpoint, which AgentCore Runtime already provides. They solve different problems:
-
Use a runtime endpoint to reach your agent. A runtime endpoint, such as
DEFAULT, controls which version of your agent callers reach.InvokeAgentRuntimecalls resolve through it, so you can keep development and production on different versions and promote or roll back without changing callers. -
Use a session endpoint to reach what your agent runs. An agent often starts other applications in its session, such as a web preview of the app it’s building, a development server, or a service it’s testing. A session endpoint is an authenticated URL that opens those applications, on only the ports that you allow.
| Runtime endpoint | Session endpoint | |
|---|---|---|
|
What it is |
Named pointer to an agent version, such as |
HTTPS URL for one runtime session. It isn’t a separate resource. |
|
Typical use |
Separate development and production, promote and roll back |
Web previews, custom APIs, streaming, gRPC, and WebSocket connections |
|
Created by |
|
Runtime, when a session starts on a runtime with |
|
How you use it |
|
Send authenticated HTTPS requests to the returned URL |
|
What it reaches |
The agent’s serving port and invocation path |
Any port in |
|
Version |
Chooses the version |
Uses the session it belongs to, which was created through a runtime endpoint |
|
Scope |
All sessions that use the endpoint |
One session |
|
Lifetime |
Until you delete it |
Tied to the session’s lifecycle |
Continue to send requests to your agent with InvokeAgentRuntime. When you invoke the agent through a runtime endpoint, Runtime returns a session endpoint URL for the session that the invocation uses. Use that URL to reach the other servers in the session.
How session endpoints work
-
Create a runtime with
allowedPortsand an application that listens on those ports. -
Start or reuse a session with a Runtime operation, such as
InvokeAgentRuntime. Read the session endpoint URL from the response header. -
Send an authenticated request to the session endpoint URL. Choose the hostname for your port and the path for your application.
-
Runtime checks access to the runtime and the requested port. It prepares compute if needed and forwards the request to your application.
The proxy preserves the application’s HTTP method, path, query string, and request body. For example, GET /preview/index.html reaches that route on your server, and POST /api/tasks reaches /api/tasks. protocolConfiguration.path does not rewrite or prepend a path to session endpoint requests.
The proxy doesn’t forward the session endpoint hostname. Your application receives an internal Runtime hostname in the Host header, and the request doesn’t include an X-Forwarded-Host header. The internal hostname can change, so don’t depend on its value.
-
If your server validates the
Hostheader, configure it to accept the requests that Runtime forwards. For example, setserver.allowedHoststotruefor the Vite dev server, or setdevServer.allowedHoststo'all'for webpack-dev-server. Other frameworks have similar settings, such asALLOWED_HOSTSin Django. -
Use relative URLs for links, assets, and redirects. Absolute URLs that your application builds from the
Hostheader point to the internal hostname, which clients can’t reach.
Start your application servers and bind them to 0.0.0.0 on their configured ports. Adding a port to allowedPorts doesn’t start or configure a server.
The agent server must also satisfy the Runtime service contract.
Configure allowed ports
Set allowedPorts in the CreateAgentRuntime request. The list follows these rules:
-
Include 1–5 entries. Each entry specifies exactly one
portor oneportRange. -
Port numbers and range endpoints must be between
8000and12000, inclusive. -
A range includes both its
fromandtoports.frommust be less than or equal toto. -
Entries must be unique and must not overlap, including a single port that falls inside another entry’s range.
-
Exclude all reserved platform ports, including
8443. Runtime rejects a range that contains even one reserved port.
Omit allowedPorts when creating a runtime if you don’t need session endpoints.
The example allows the default HTTP serving port 8080, web application ports 8081–8086, and gRPC port 10000. The range counts as one entry.
Replace the Region, image URI, and execution role ARN with your values. Use an AWS SDK version that supports allowedPorts and the serving port and invocation path settings.
import boto3 region = "us-west-2" control = boto3.client("bedrock-agentcore-control", region_name=region) runtime = control.create_agent_runtime( agentRuntimeName="session_endpoint_agent", agentRuntimeArtifact={ "containerConfiguration": { "containerUri": ( "123456789012.dkr.ecr.us-west-2.amazonaws.com/my-agent:latest" ) } }, roleArn="arn:aws:iam::123456789012:role/AgentCoreRuntimeExecutionRole", networkConfiguration={"networkMode": "PUBLIC"}, protocolConfiguration={"serverProtocol": "HTTP"}, allowedPorts=[ {"port": 8080}, {"portRange": {"from": 8081, "to": 8086}}, {"port": 10000}, ], ) agent_runtime_arn = runtime["agentRuntimeArn"]
You can also combine allowedPorts with a custom protocolConfiguration.port or .path. If you want to access the custom serving port through the session endpoint URL, include that port in allowedPorts.
Get the session endpoint URL
After the runtime reaches READY status, invoke it to establish a session. For a runtime with session endpoints enabled, the response can include this header:
X-Amzn-Bedrock-AgentCore-Runtime-Session-Endpoint-Url
The following operations can return the header:
-
InvokeAgentRuntime -
InvokeAgentRuntimeWithWebSocketStream -
InvokeAgentRuntimeCommand -
InvokeAgentRuntimeCommandShell -
GetAgentCard
For the two WebSocket operations, read the header from the HTTP 101 Switching Protocols handshake response. SDKs that model the header expose it as sessionEndpointUrl.
The header is optional. Runtime omits it when session endpoints aren’t enabled or a session endpoint URL isn’t available. CreateAgentRuntime stores the configuration but does not return a session endpoint URL.
The following IAM-authenticated example invokes the runtime and reads the URL. It uses sessionEndpointUrl when your SDK exposes it, and otherwise reads the raw header. You can read the URL before consuming the response body.
import json import uuid client = boto3.client("bedrock-agentcore", region_name=region) session_id = str(uuid.uuid4()) response = client.invoke_agent_runtime( agentRuntimeArn=agent_runtime_arn, runtimeSessionId=session_id, contentType="application/json", payload=json.dumps({"prompt": "Hello"}).encode("utf-8"), ) try: headers = response["ResponseMetadata"]["HTTPHeaders"] session_endpoint_url = response.get("sessionEndpointUrl") or headers.get( "x-amzn-bedrock-agentcore-runtime-session-endpoint-url" ) if not session_endpoint_url: raise RuntimeError( "No session endpoint URL returned. Check the allowedPorts configuration." ) print(response["response"].read().decode("utf-8")) finally: response["response"].close()
For an OAuth-configured runtime, send an authenticated HTTPS invocation and read the same response header. For instructions, see Authenticate and authorize with Inbound Auth and Outbound Auth.
Store the returned URL with the corresponding session ID. The opaque identifier in the URL is different from runtimeSessionId; use the URL returned by Runtime.
Select the destination port and path
An unprefixed session endpoint URL uses the agent’s configured serving port. If protocolConfiguration.port is omitted, it uses the protocol default: 8080 for HTTP and AG-UI, 8000 for MCP, or 9000 for A2A.
To select another port, prefix the first hostname label with the port number and two hyphens (--). Keep the session endpoint identifier and the service domain from the returned URL.
https://<session-endpoint-id>.<service-domain>/application/path https://8081--<session-endpoint-id>.<service-domain>/application/path https://10000--<session-endpoint-id>.<service-domain>/package.Service/Method
The first URL uses the serving port. The second selects port 8081, and the third selects port 10000. The client connects over TLS on port 443; the hostname prefix selects the destination port inside the session.
Every selected port must be in allowedPorts. This includes the serving port used by an unprefixed URL.
You can allow only additional application ports and omit the serving port from the list. In that case, use a port-prefixed URL. Runtime denies requests to the unprefixed URL with HTTP 403.
For the example runtime, construct a preview URL for port 8081 as follows:
from urllib.parse import urlsplit, urlunsplit parts = urlsplit(session_endpoint_url) preview_url = urlunsplit( ("https", f"8081--{parts.hostname}", "/", "", "") )
Append the path and query string that your application expects. Authenticate requests for web preview assets as well as requests for the initial page.
Authenticate requests
Use the inbound authentication mode configured for your runtime. Each HTTP request, HTTP/2 stream, and WebSocket handshake requires authentication. Possession of a session endpoint URL does not grant access.
IAM and Signature Version 4
IAM callers need bedrock-agentcore:InvokeAgentRuntimeProxy permission for the runtime and runtime endpoint. If you use InvokeAgentRuntime to obtain the URL, you also need bedrock-agentcore:InvokeAgentRuntime permission.
The following policy grants those two actions for one runtime and its DEFAULT endpoint. Replace the resource ARNs with your runtime and endpoint ARNs. Attach the policy to the calling identity.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "bedrock-agentcore:InvokeAgentRuntime", "bedrock-agentcore:InvokeAgentRuntimeProxy" ], "Resource": [ "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/session_endpoint_agent-a1b2c3d4e5", "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/session_endpoint_agent-a1b2c3d4e5/runtime-endpoint/DEFAULT" ] } ] }
Sign requests with Signature Version 4 (SigV4), using the signing service name bedrock-agentcore and the runtime’s AWS Region. Sign the destination hostname, HTTP method, path, query string, and applicable headers of the request you send.
For session endpoint requests, X-Amz-Content-Sha256 is optional. Use the following payload hash in the canonical SigV4 request:
-
If you omit the header, use the SHA-256 hash of an empty payload, even when the application request has a body.
-
If you supply the header, use its value as the payload hash. Set the header before signing so that the signature matches the value you send.
When you omit the header, sign without the application body and attach the body after signing.
The following example uses Boto3 credentials and requests to make a signed GET request to the preview URL without X-Amz-Content-Sha256. Install boto3 and requests in your client environment and configure AWS credentials before running it.
For requests without a body, such as this GET request, send Content-Length: 0 so that the application server receives an explicitly empty body. The example sets the header before signing.
import boto3 import requests from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest credentials = boto3.Session(region_name=region).get_credentials() if credentials is None: raise RuntimeError("Configure AWS credentials before making this request.") request = AWSRequest( method="GET", url=preview_url, headers={"Content-Length": "0"}, ) SigV4Auth( credentials.get_frozen_credentials(), "bedrock-agentcore", region ).add_auth(request) result = requests.get( request.url, headers=dict(request.headers), timeout=60, allow_redirects=False, ) result.raise_for_status() print(result.text)
If you follow an application redirect, sign a new request for the redirect destination.
OAuth bearer tokens
For a runtime configured with an inbound OAuth authorizer, send a valid bearer token in the Authorization header. The token must satisfy the runtime’s authorizer configuration. For setup details, see Authenticate and authorize with Inbound Auth and Outbound Auth.
Set PREVIEW_URL to the URL for your application’s allowed port and ACCESS_TOKEN to your OAuth access token.
curl --request GET \ --header "Authorization: Bearer ${ACCESS_TOKEN}" \ "${PREVIEW_URL}"
Runtime handles inbound authentication and filters service authentication headers and reserved transport headers before forwarding the request to your application.
HTTP, gRPC, and WebSocket connections
Use a client that supports the protocol exposed by your application server:
- HTTP/1.1
-
Use HTTPS with the application’s HTTP method, path, query string, and payload. Responses can be streamed, including server-sent events (SSE).
- HTTP/2 and gRPC
-
Connect to the session endpoint URL using TLS and HTTP/2. To select HTTP/2 over cleartext (
h2c) for the application connection, setX-Amzn-Bedrock-AgentCore-Runtime-Session-Target-Transport: h2c. The application connection does not use TLS.For gRPC, use the port-prefixed hostname for your gRPC server. Supply authentication with each RPC.
- WebSocket
-
Use
wsswith the session hostname, optional port prefix, and your application’s WebSocket path. Use a client that can supply authentication headers in its HTTP/1.1 upgrade request.
The target-transport header controls only the connection from Runtime to the application server. Your client connection to the session endpoint URL still uses TLS.
Omit this header for an HTTP/1.1 application server or a WebSocket upgrade. When provided, the supported value is h2c.
These connections use your application’s routes. For example, a WebSocket server on port 8081 with a /live route is addressed as follows:
wss://8081--<session-endpoint-id>.<service-domain>/live
Handle proxy errors
Runtime relays application responses using the application’s status, body, and protocol. Platform proxy errors have an HTTP status, an empty body, and the following attribution header:
X-Amzn-Bedrock-AgentCore-Runtime-Error
Use the header to distinguish a platform error from an application response with the same HTTP status. Platform errors aren’t wrapped in MCP, A2A, or AG-UI response envelopes.
| HTTP status | Proxy error | What to check |
|---|---|---|
|
|
|
Check the URL, request format, and transport settings. |
|
|
|
Supply valid credentials for the runtime’s configured authentication mode. |
|
|
|
Check SigV4 signing or other authorization requirements and verify that the selected port is in |
|
|
|
Verify that you’re using a returned session endpoint URL and that the session still exists. |
|
|
|
A session operation is in progress. Retry with bounded backoff when the application request is safe to retry. |
|
|
|
The application didn’t become ready or respond within the timeout. Check application startup, readiness, and response times. |
|
|
|
Reduce the request rate and use bounded backoff. |
|
|
|
An unexpected platform error occurred. |
|
|
|
Check that the application is listening on the selected port and bound to |
|
|
|
The service cannot currently accept or prepare the request. Use bounded backoff for requests that are safe to retry. |
An error after response headers have been sent, or after a WebSocket upgrade, can terminate the stream or connection. A second HTTP error response cannot replace a response that has already started.
Log session endpoint requests in CloudTrail
AWS CloudTrail records session endpoint requests as data events with the event name InvokeAgentRuntimeProxy and the event source bedrock-agentcore.amazonaws.com. Like InvokeAgentRuntime events, these events use the AWS::BedrockAgentCore::Runtime resource type.
Data events aren’t logged by default, and they don’t appear in CloudTrail Event history. To record session endpoint requests, create a trail or event data store and add an advanced event selector for the AWS::BedrockAgentCore::Runtime resource type. To log only session endpoint requests, also filter on the InvokeAgentRuntimeProxy event name.
Important
Additional charges apply for data events. A web preview can send many requests, one for each page, asset, and API call. For more information, see AWS CloudTrail pricing
Session lifecycle and reconnection
Session endpoints address runtime sessions and follow the session lifecycle settings. A request can wait while Runtime prepares compute. Configure client timeouts for your application’s startup and streaming behavior.
Compute replacement can interrupt active HTTP streams, gRPC calls, and WebSocket connections. Reconnect with authentication to the session endpoint URL while the session remains available.
Reconnection creates a new connection. It doesn’t guarantee that application memory or an interrupted response is preserved. For persistence options, see File system configurations for AgentCore Runtime.
Retry only requests that your application can safely repeat. A failed connection doesn’t prove that the server didn’t execute a request.
Use bounded retries and backoff. Before replaying a request, apply your application’s idempotency rules.