docs/snippets/integrations/agentcore/index.mdx
import { Callout } from "fumadocs-ui/components/callout"; import { Tabs, Tab } from "fumadocs-ui/components/tabs"; import { Cards, Card } from "fumadocs-ui/components/card"; import { PaintbrushIcon, WrenchIcon, RepeatIcon } from "lucide-react"; import { TailoredContent, TailoredContentOption, } from "@/components/react/tailored-content.tsx"; import { AgentCoreCommandTabs } from "@/components/content/agentcore-command-tabs";
AWS Bedrock AgentCore gives you a secure, serverless runtime for deploying AG-UI agents at scale — handling auth, session isolation, and infrastructure. CopilotKit gives those agents a production-ready frontend:
Chat UI · Shared State · Generative UI · Human-in-the-loop
The two connect through CopilotKit Runtime, a lightweight server-side layer that sits between your browser and AgentCore. It's the same runtime you'd use with any CopilotKit-powered agent — AgentCore just requires it to run server-side (browsers can't call AgentCore directly due to SigV4/OAuth2 authentication).
Browser → CopilotKit Runtime → AgentCore Runtime → your agent
<AgentCoreCommandTabs
framework={props.framework}
lgCommand="npx copilotkit@latest create -f agentcore-langgraph"
stCommand="npx copilotkit@latest create -f agentcore-strands"
/>
The CLI downloads the full AgentCore template and sets up `config.yaml` for you.
</Step>
<Step>
### Configure
Open `config.yaml` and set your details:
```yaml title="config.yaml"
stack_name_base: my-agentcore-app # prefix for all AWS resources (max 35 chars)
admin_user_email: [email protected] # where your Cognito invite will be sent
```
</Step>
<Step>
### Deploy
One command deploys everything — CDK infrastructure, AgentCore Runtime, and the frontend:
<AgentCoreCommandTabs
framework={props.framework}
lgCommand="./deploy-langgraph.sh"
stCommand="./deploy-strands.sh"
/>
</Step>
<Step>
### 🎉 Open your app
The deploy script prints an Amplify URL when it finishes. Open it and sign in with your `admin_user_email`.
</Step>
<Step>
### Run locally
To run the full stack locally — agent, CopilotKit runtime, and frontend — without deploying:
```bash
cd docker
cp .env.example .env
# Fill in AWS credentials and STACK_NAME
./up.sh --build
```
| Service | Port | Description |
|---|---|---|
| `agent` | 8080 | Your agent, hot-reloads on `.py` changes |
| `runtime` | 3001 | CopilotKit Runtime |
| `frontend` | 3000 | Vite dev server |
</Step>
<Step>
### Tear down
When done, delete all AWS resources to stop charges:
```bash
cd infra-cdk && npx cdk destroy --all
```
</Step>
</TailoredContentOption>
<TailoredContentOption
id="existing"
title="I already have an agent"
description="I've followed the AWS guide and have an AG-UI agent deployed on AgentCore Runtime."
>
<Step>
### Install CopilotKit
<Callout type="info" title="Deploying your AG-UI agent on AgentCore">
This path assumes you already have an AG-UI-compatible agent deployed on AgentCore Runtime.
If not, follow AWS's [Deploy an AG-UI agent to AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-agui.html)
guide first, then return here.
</Callout>
```npm
npm install @copilotkit/react-core @copilotkit/react-ui @copilotkit/runtime @ag-ui/client rxjs
```
</Step>
<Step>
### Set up CopilotKit Runtime
CopilotKit Runtime is the server-side layer that connects your frontend to AgentCore. It handles
the communication protocol, middleware, and — with AgentCore specifically — the server-side
authentication that browsers can't perform directly.
Create an API route:
```typescript title="app/api/copilotkit/route.ts"
import {
CopilotRuntime,
ExperimentalEmptyAdapter,
copilotRuntimeNextJSAppRouterEndpoint,
} from "@copilotkit/runtime";
import { HttpAgent } from "@ag-ui/client";
import { NextRequest } from "next/server";
import { AgentCoreRunner } from "./agent-core-runner";
const runtime = new CopilotRuntime({
agents: {
my_agent: new HttpAgent({
url: process.env.AGENTCORE_ENDPOINT_URL!, // your /invocations URL
headers: {
Authorization: `Bearer ${process.env.AGENTCORE_ACCESS_TOKEN}`,
},
}),
},
runner: new AgentCoreRunner(),
});
export const POST = async (req: NextRequest) => {
const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
runtime,
serviceAdapter: new ExperimentalEmptyAdapter(),
endpoint: "/api/copilotkit",
});
return handleRequest(req);
};
```
<Callout type="info" title="What is AGENTCORE_ENDPOINT_URL?">
This is the invocation URL for your deployed AgentCore Runtime — the URL you call to reach
your agent. It takes the form:
`https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{encoded-arn}/invocations`
</Callout>
<Callout type="info" title="Auth in production">
The example above uses a static token for simplicity. In production you'll want to pass the
user's Cognito JWT from the frontend through to AgentCore. See the
[full-stack example](/agentcore/full-stack-example) for a complete Cognito OIDC implementation.
</Callout>
</Step>
<Step>
### Add the AgentCoreRunner
AgentCore's memory layer stores conversation history server-side. When CopilotKit reconnects
to an existing thread (e.g. on page refresh), two issues arise that require a custom runner:
1. **Unknown threads** — CopilotKit may call `connect()` before any `run()` has happened.
Without handling this, you'll get an error on first load.
2. **Missing tool-call results** — AgentCore's replayed history includes assistant messages
with tool calls, but omits the corresponding results. CopilotKit needs those to reconcile
its message state, so the runner synthesises empty results for each past tool call.
Create the runner file alongside your API route:
```typescript title="app/api/copilotkit/agent-core-runner.ts"
import {
EventType,
type BaseEvent,
type Message,
type MessagesSnapshotEvent,
type ToolCall,
type ToolCallResultEvent,
} from "@ag-ui/client";
import { InMemoryAgentRunner } from "@copilotkit/runtime";
import { concatMap, of } from "rxjs";
import { randomUUID } from "node:crypto";
export class AgentCoreRunner extends InMemoryAgentRunner {
private readonly knownThreadIds = new Set<string>();
override run(request: Parameters<InMemoryAgentRunner["run"]>[0]) {
if (request.threadId) this.knownThreadIds.add(request.threadId);
return super.run(request);
}
override connect(request: Parameters<InMemoryAgentRunner["connect"]>[0]) {
if (!request.threadId || !this.knownThreadIds.has(request.threadId)) {
const threadId = request.threadId ?? randomUUID();
const runId = randomUUID();
return of<BaseEvent>(
{ type: EventType.RUN_STARTED, threadId, runId },
{ type: EventType.MESSAGES_SNAPSHOT, messages: [] },
{ type: EventType.RUN_FINISHED, threadId, runId },
);
}
return super.connect(request).pipe(
concatMap((event: BaseEvent) => {
if (event.type !== EventType.MESSAGES_SNAPSHOT) return of(event);
const snapshot = event as MessagesSnapshotEvent;
const replayedResults: ToolCallResultEvent[] = snapshot.messages.flatMap(
(message: Message) => {
if (message.role !== "assistant" || !message.toolCalls?.length) return [];
return message.toolCalls.map<ToolCallResultEvent>((toolCall: ToolCall) => ({
type: EventType.TOOL_CALL_RESULT,
toolCallId: toolCall.id,
messageId: `${toolCall.id}-result`,
content: "",
role: "tool",
}));
},
);
return of<BaseEvent>(...replayedResults, snapshot);
}),
);
}
}
```
</Step>
<Step>
### Add the CopilotKit provider
```tsx title="app/layout.tsx"
import { CopilotKit } from "@copilotkit/react-core";
import "@copilotkit/react-ui/styles.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<CopilotKit runtimeUrl="/api/copilotkit" agent="my_agent">
{children}
</CopilotKit>
</body>
</html>
);
}
```
</Step>
<Step>
### Add the chat interface
```tsx title="app/page.tsx"
import { CopilotSidebar } from "@copilotkit/react-ui";
export default function Page() {
return (
<main>
<h1>My App</h1>
<CopilotSidebar />
</main>
);
}
```
</Step>
<Step>
### 🎉 Run it
Point the Next.js app at the AgentCore runtime you deployed via AWS's
[Deploy an AG-UI agent to AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-agui.html)
guide. Create `.env.local`:
```bash title=".env.local"
AGENTCORE_ENDPOINT_URL=https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{encoded-arn}/invocations
AGENTCORE_ACCESS_TOKEN=<your-bearer-token>
```
Then:
```bash
npm run dev
```
Navigate to `localhost:3000`. The frontend runs locally while the agent stays on AgentCore —
the `/api/copilotkit` route forwards each call to the invocation URL using your token.
</Step>
</TailoredContentOption>