Skip to content

Integrate CopilotKit (AG-UI)

Use this when you have a CopilotKit React frontend and need to connect it to an awaken agent server via the AG-UI protocol.

  • A working awaken agent runtime (see First Agent)
  • Feature server enabled on the awaken crate
  • Node.js project with @copilotkit/react-core and @copilotkit/react-ui installed
[dependencies]
awaken = { git = "https://github.com/AwakenWorks/awaken", features = ["server"] }
tokio = { version = "1", features = ["full"] }
async-trait = "0.1"
serde_json = "1"
tracing-subscriber = "0.3"
  1. Build the backend server.
use std::sync::Arc;
use awaken::engine::GenaiExecutor;
use awaken::contract::storage::ThreadRunStore;
use awaken::registry_spec::ModelSpec;
use awaken::registry_spec::AgentSpec;
use awaken::stores::{InMemoryMailboxStore, InMemoryStore};
use awaken::AgentRuntimeBuilder;
use awaken::server::app::{ServerState, ServerConfig};
use awaken::server::mailbox::{Mailbox, MailboxConfig};
use awaken::server::routes::build_router;
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().with_target(true).init();
let agent_spec = AgentSpec::new("copilotkit-agent")
.with_model_id("gpt-4o-mini")
.with_system_prompt(
"You are a CopilotKit-powered assistant. \
Update shared state and suggest actions when appropriate.",
)
.with_max_rounds(10);
let runtime = AgentRuntimeBuilder::new()
.with_provider("openai", Arc::new(GenaiExecutor::new()))
.with_model(ModelSpec::new("gpt-4o-mini", "openai", "gpt-4o-mini"))
.with_agent_spec(agent_spec)
.build()
.expect("failed to build runtime");
let runtime = Arc::new(runtime);
let store = Arc::new(InMemoryStore::new());
let resolver = runtime.resolver_arc();
let mailbox_store = Arc::new(InMemoryMailboxStore::new());
let mailbox = Arc::new(Mailbox::new(
runtime.clone(),
mailbox_store as Arc<dyn awaken::contract::MailboxStore>,
store.clone() as Arc<dyn ThreadRunStore>,
format!("copilotkit:{}", std::process::id()),
MailboxConfig::default(),
));
let state = ServerState::new(
runtime,
mailbox,
store as Arc<dyn ThreadRunStore>,
resolver,
ServerConfig {
address: "127.0.0.1:3000".into(),
..Default::default()
},
);
let app = build_router().with_state(state);
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.expect("failed to bind");
axum::serve(listener, app).await.expect("server crashed");
}

The server automatically registers AG-UI routes at:

  • POST /v1/ag-ui/run — create a new run and stream AG-UI events
  • POST /v1/ag-ui/threads/:thread_id/runs — start a thread-scoped run
  • POST /v1/ag-ui/agents/:agent_id/runs — start an agent-scoped run
  • POST /v1/ag-ui/threads/:thread_id/interrupt — interrupt a running thread
  • GET /v1/ag-ui/threads/:thread_id/replay — replay durable protocol frames when a ProtocolReplayLog is wired
  • GET /v1/ag-ui/threads/:id/messages — retrieve thread messages
  1. Connect the CopilotKit frontend.

    Install CopilotKit packages:

Terminal window
npm install @copilotkit/react-core @copilotkit/react-ui

Wrap your app with the CopilotKit provider:

import { CopilotKit } from "@copilotkit/react-core";
import { CopilotChat } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
export default function App() {
return (
<CopilotKit runtimeUrl="http://localhost:3000/v1/ag-ui/run">
<CopilotChat
labels={{ title: "Agent", initial: "How can I help?" }}
/>
</CopilotKit>
);
}
  1. Run both sides.
Terminal window
# Terminal 1: backend
cargo run
# Terminal 2: frontend
npm run dev
  1. Open the frontend in a browser.
  2. Send a message through the CopilotChat widget.
  3. Confirm streaming text appears in the chat UI.
  4. Check the backend logs for RunStart and RunFinish events.
SymptomCauseFix
CORS error in browserNo CORS middlewareAdd tower-http CORS layer to the axum router
CopilotKit shows “connection failed”Wrong runtimeUrlConfirm it points to http://localhost:3000/v1/ag-ui/run (the AG-UI run endpoint, not the namespace)
Events arrive but UI does not updateAG-UI event format mismatchEnsure CopilotKit version is compatible with AG-UI protocol
404 on /v1/ag-ui/runMissing server featureEnable features = ["server"] in Cargo.toml
  • examples/copilotkit-starter/agent/src/main.rs
PathPurpose
crates/awaken-server/src/protocols/ag_ui/http.rsAG-UI route handlers
crates/awaken-server/src/protocols/ag_ui/encoder.rsAG-UI SSE event encoder
crates/awaken-server/src/routes.rsUnified router builder
crates/awaken-server/src/app.rsServerState and ServerConfig
examples/copilotkit-starter/agent/src/main.rsBackend entry for the CopilotKit starter