copilotkit/copilotkit

a2ui-renderer

Render A2UI (Agent-to-UI declarative surfaces) in CopilotKit v2.

소스 보기

사용 방법

  1. 설치 명령을 복사하고 자신의 에이전트 환경에 설치하기 전에 소스 패키지를 확인하세요.
  2. 필요한 도구, 인증 정보, 지원 환경은 원본 문서에서 확인하세요.
  3. 입력과 원하는 산출물을 설명하고 출처와 결과를 대조하세요.
npx skills add https://github.com/copilotkit/copilotkit --skill a2ui-renderer

시작 전 확인

  • 설치에는 모델 구독, API 한도, 파일 접근 권한이 포함되지 않습니다.
  • 별점 수와 설치 수는 활동 지표이며 독립적인 품질·보안 검증이 아닙니다.
원본 Skill 문서

원본 저장소의 제목, 예시, 코드, 표, 링크, 이미지를 유지해 표시합니다.

This skill builds on copilotkit/react-core (for CopilotKit provider fundamentals) and copilotkit/runtime (for CopilotRuntime fundamentals). Read those first.

Setup

A2UI has two halves. The runtime declares a2ui middleware; the client enables the a2ui prop on the provider. Once both are set, /info flags A2UI and the client auto-mounts createA2UIMessageRenderer — you do NOT wire renderActivityMessages yourself.

Runtime side (app/routes/api.copilotkit.$.tsx)

tsx
import type { Route } from "./+types/api.copilotkit.$";
import {
  CopilotRuntime,
  createCopilotRuntimeHandler,
  BuiltInAgent,
  convertInputToTanStackAI,
} from "@copilotkit/runtime/v2";
import { chat } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";

const agent = new BuiltInAgent({
  type: "tanstack",
  factory: ({ input, abortController }) => {
    const { messages, systemPrompts } = convertInputToTanStackAI(input);
    return chat({
      adapter: openaiText("gpt-4o"),
      messages,
      systemPrompts,
      abortController,
    });
  },
});

const runtime = new CopilotRuntime({
  agents: { default: agent },
  // Enabling this key causes /info to advertise A2UI to the client.
  a2ui: {},
});

const handler = createCopilotRuntimeHandler({
  runtime,
  basePath: "/api/copilotkit",
});

export async function loader({ request }: Route.LoaderArgs) {
  return handler(request);
}
export async function action({ request }: Route.ActionArgs) {
  return handler(request);
}

Client side (app/root.tsx or the app shell)

tsx
import { CopilotKit, CopilotChat } from "@copilotkit/react-core/v2";
import "@copilotkit/react-core/v2/styles.css";

export default function App() {
  return (
    <CopilotKit
      runtimeUrl="/api/copilotkit"
      a2ui={{
        theme: {
          // Theme object forwarded to A2UIProvider → ThemeProvider.
          // Tokens map to A2UI's basic catalog CSS vars.
          colors: { primary: "#0ea5e9" },
        },
      }}
    >
      <CopilotChat agentId="default" className="h-full" />
    </CopilotKit>
  );
}

Core Patterns

Custom catalog

Pass a custom catalog to extend the built-in component set. createCatalog and extractSchema let the agent see what components it may render.

tsx
import { createCatalog } from "@copilotkit/a2ui-renderer";
import { z } from "zod";

const theme = { colors: { primary: "#0ea5e9" } };

// Definitions are platform-agnostic (Zod schemas + descriptions).
// Renderers are platform-specific (React components).
// TypeScript enforces that renderer keys match definition keys exactly.
const definitions = {
  ProductCard: {
    description: "A product card with title and price",
    props: z.object({ title: z.string(), price: z.number() }),
  },
};

const catalog = createCatalog(
  definitions,
  {
    ProductCard: ({ props }) => (
      <div className="rounded-xl border p-3">
        <div className="font-medium">{props.title}</div>
        <div className="text-sm text-muted-foreground">${props.price}</div>
      </div>
    ),
  },
  { includeBasicCatalog: true },
);

<CopilotKit runtimeUrl="/api/copilotkit" a2ui={{ theme, catalog }}>
  <CopilotChat agentId="default" />
</CopilotKit>;

extractSchema(definitions) is available for passing a JSON-serializable view of the definitions to the runtime's a2ui.schema config — it is not a generic type helper. Type parameters erase at runtime; the agent needs a real runtime schema value (Zod).

Override the loading skeleton

tsx
<CopilotKit
  runtimeUrl="/api/copilotkit"
  a2ui={{
    theme,
    loadingComponent: () => <div className="animate-pulse">Building UI…</div>,
  }}
>
  <CopilotChat agentId="default" />
</CopilotKit>

Common Mistakes

CRITICAL forgetting runtime.a2ui

Wrong:

tsx
// server
new CopilotRuntime({ agents: { default: agent } });
// client
<CopilotKit runtimeUrl="/api/copilotkit" a2ui={{ theme }} />;

Correct:

tsx
// server
new CopilotRuntime({ agents: { default: agent }, a2ui: {} });
// client
<CopilotKit runtimeUrl="/api/copilotkit" a2ui={{ theme }} />;

Without runtime.a2ui, /info never flags A2UI and the provider's a2ui prop silently no-ops — the renderer never mounts.

Source: packages/runtime/src/v2/runtime/core/runtime.ts:55-58,217,242

HIGH manually wiring renderActivityMessages for A2UI

Wrong:

tsx
import { createA2UIMessageRenderer } from "@copilotkit/react-core/v2";

<CopilotKit
  runtimeUrl="/api/copilotkit"
  renderActivityMessages={[createA2UIMessageRenderer({ theme })]}
/>;

Correct:

tsx
<CopilotKit runtimeUrl="/api/copilotkit" a2ui={{ theme }} />

The CopilotKit provider auto-detects runtime A2UI via /info and injects the built-in renderer. Passing it through renderActivityMessages duplicates the renderer and can race with the auto-injected one.

Source: packages/react-core/src/v2/providers/CopilotKitProvider.tsx:188-222,294-296

MEDIUM re-emitting createSurface on every snapshot

Wrong:

python
# Pseudocode — inside your agent generator. Exact API names/kwargs vary by
# A2UI SDK version; consult your SDK's docs for real call shapes.
async def agent_generator():
    # agent re-emits createSurface operation on every state delta
    async for update in stream:
        yield a2ui.create_surface(surface_id="main", ...)  # every tick
        yield a2ui.update_components(...)

Correct:

python
# Pseudocode — inside your agent generator.
# Emit createSurface once per surfaceId; use updateComponents / updateDataModel
# for changes.
async def agent_generator():
    yield a2ui.create_surface(surface_id="main", ...)  # once
    async for update in stream:
        yield a2ui.update_components(surface_id="main", ...)

The MessageProcessor dedups on surfaceId but re-emitting is an agent-side bug — the client re-runs reconciliation logic for nothing and flickers.

Source: packages/react-core/src/v2/a2ui/A2UIMessageRenderer.tsx:218-226

MEDIUM custom action bridge without a2uiAction cleanup

Wrong:

ts
copilotkit.setProperties({ ...copilotkit.properties, a2uiAction: msg });
await copilotkit.runAgent({ agent });
// no finally — a2uiAction leaks into the next run's properties

Correct:

ts
try {
  copilotkit.setProperties({ ...copilotkit.properties, a2uiAction: msg });
  await copilotkit.runAgent({ agent });
} finally {
  if (copilotkit.properties) {
    const { a2uiAction, ...rest } = copilotkit.properties;
    copilotkit.setProperties(rest);
  }
}

The built-in bridge always strips a2uiAction in finally, guarded by a copilotkit.properties null-check so it can't mask the original runAgent error with a TypeError during destructuring. Skipping cleanup keeps the previous action attached to subsequent runs.

Source: packages/react-core/src/v2/a2ui/A2UIMessageRenderer.tsx:146-167

MEDIUM installing @copilotkitnext/a2ui-renderer

Wrong:

ts
import { createA2UIMessageRenderer } from "@copilotkitnext/a2ui-renderer";

Correct:

ts
// Low-level primitives (rarely needed — the CopilotKit provider's a2ui prop is the default path):
import {
  A2UIProvider,
  A2UIRenderer,
  createCatalog,
} from "@copilotkit/a2ui-renderer";
// Auto-mounted renderer lives in react-core/v2:
import { createA2UIMessageRenderer } from "@copilotkit/react-core/v2";

This package ships as @copilotkit/a2ui-renderer, not @copilotkitnext/a2ui-renderer. The @copilotkitnext/ scope is reserved for other packages that ship under it separately — do not assume it applies here.

Source: packages/a2ui-renderer/package.json

관련 작업

같은 저장소의 Skills

더 많은 Skills

모든 Skills
copilotkit
커뮤니티

channels-setup

Use when a developer wants to build their first CopilotKit Channels agent and get it answering in Slack or Microsoft Teams: "set up a channel", "connect my agent to Slack", "get my agent into Teams", or starting from nothing and wanting a working channel end to end. Covers the whole path: inspecting or scaffolding the project, building the AG-UI agent, creating and reconciling the managed Channel with the public CopilotKit CLI, running the long-running host, and proving a real provider mention g

설치 수
2
GitHub Stars
3.8만
업데이트
10월 20일
copilotkit
커뮤니티

copilotkit

Use for any CopilotKit question — adding it to an app, chat UI, frontend or server tools, generative UI, shared state, human-in-the-loop, agent frameworks (LangGraph, CrewAI, Mastra, ADK, PydanticAI, and others), the runtime, Intelligence, threads, voice, or diagnosing something that is not working. Do not answer from memory: this skill exists to point you at the current documentation and source, both of which you can read.

설치 수
2
GitHub Stars
3.8만
업데이트
10월 20일
copilotkit
커뮤니티

inspector-docs

Keeps CopilotKit docs pointing at shipped Inspector panes so readers open the overlay. Use when adding, changing, renaming, or removing an Inspector pane, tab, or overlay action in @copilotkit/web-inspector, or when editing docs that mention Inspector. Don't use for Inspector UI polish that does not add a pane, for CLI or agent-prompt copy, or for unshipped Inspector ideas.

설치 수
2
GitHub Stars
3.8만
업데이트
10월 20일
copilotkit
커뮤니티

inspector-workbench

Runs Inspector UI work on the standalone Threads state lab so the agent can see the overlay. Use when a CopilotKit employee asks an agent to fix, polish, add, or debug Inspector UI, chrome, panes, overlay actions, launcher, Home, Threads, Playground, Memory, or any visual behavior in @copilotkit/web-inspector. Don't use for docs-only Callout updates (load inspector-docs), runtime or core changes with no Inspector UI, showcase cell work, or reading Inspector as a consumer inside an app.

설치 수
2
GitHub Stars
3.8만
업데이트
10월 20일