CopilotKit 整体架构总览

前端组件如何注册到后端agent服务中的
通过CopilotKit 生成式UI框架 了解到,根据开放程度可以分成3类组件
- controrolled Generative UI
- declarative Generative UI
- open Generative UI
其中第2和3类都是在CopilotRuntime 中注册的,注册后在后续发给agent的http请求中会以上下文的方式(其实也是参数)传递给agent
1 | onst langGraphAgent = new LangGraphHttpAgent({ url: "http://localhost:8004" }); |
三类组件注册流程总览

源码分析:
已知CopilotKit 是一个基于agui协议的框架,agui协议是基于http的上层协议
LangGraphHttpAgent 从httpAgent 中继承
本身的作用就是通过http协议与agent进行通信
The HttpAgent extends AbstractAgent to provide HTTP-based connectivity to remote AI agents. It handles the request/response cycle and transforms the HTTP event stream into standard Agent User Interaction Protocol events.
CopilotRuntime 是一个桥接器,用于前端和后端agent服务之间的通信,控制请求发送,信息处理等操作
createCopilotEndpoint 会创建一个node服务,利用CopilotRuntime实例,将tools 信息给到agent 并处理请求过程中的信息,返回给前端


对于第1类 使用 useComponent 进行组件注册的过程会使用useFrontendTool 方法,将组件注册到copilotkit 实例的tools 中

对于 使用 
从输入框提交信息后会经过copiloykit 实例发起runAgent
在初始化创建的时候就会传入tools, 后续在connectAgent 和 runAgent 中都会将tools 信息传递给后端agent

agent 本身是一个http-agent
1 | var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAgent { |

多样的UI界面是谁渲染的
UI 渲染总览流程

UI 的渲染依然通过前端组件渲染,只不过在渲染时会根据messages 中的返回信息决定使用组件的类型,选择不同的组件进行渲染。
因此, agent 会决定渲染的组件类型,前端组件只是根据组件类型进行渲染。
源码分析:
1 | const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, { |
renderMessageBlock 是一个函数,用于根据消息的类型渲染不同的组件

controlled Generative UI 渲染逻辑

第一类渲染时走 role: “assistant”



1 | const { Component: AssistantComponent, slotProps: assistantSlotProps } = |
1 | const renderToolCall = useCallback( |
1 | const ToolCallRenderer = React.memo( |
注意上面的RenderComponent
1 | <RenderComponent |
是经过useFrontendTool 注册的组件是的render

非controlled Generative UI 渲染逻辑

第二类和第三类的渲染逻辑 走 role: “activity” 的渲染逻辑

1 | const { renderActivityMessage } = useRenderActivityMessage(); |

1 | ----------------------- useRenderActivityMessage -------------------------------- |
注册时的处理第2类和第3类 的render
a2UI
dynamic schema UI 渲染messages
fixed schema UI 渲染messages

1 | /** |
processMessages 通过执行不同的操作实现a2UI的渲染

1 | processCreateSurfaceMessage(message) { |
mcp 渲染逻辑

详见下面代码, 主要逻辑就是根据mcp配置通过 agent 发起请求获取到html 再通过通知方式将内容填到创建好的iframe中
1 | /** |
open Generative UI 渲染逻辑

全开放式渲染逻辑过程直接从后端agent content 中获取html 再通过构建沙河环境,将html 渲染到iframe中
1 |
|


CopilotRuntime
本质是一个代理, 或者代理适配器(多个agent存在时),寻找后端agent 服务,并将前端请求转发给后端agent 服务
On the server, CopilotRuntime accepts a map of AG-UI AbstractAgent instances. A framework adapter, an HttpAgent pointing at a remote server, and a custom implementation all use the same request path:
- The runtime resolves the target agent by ID.
- It clones the agent for request isolation and supplies messages, state, and thread context.
- AgentRunner executes the agent and receives AG-UI events.
- The runtime encodes those events as SSE and streams them to the frontend proxy.
- The backend framework can change without forcing a corresponding change to the frontend AG-UI contract.
它是一个框架无关代理,所以也可以用在支持Fetch API的node 层 运行时中
Deploy to any runtime
AGUI 协议
abstractAgent
[AbstractAgent Api] (https://docs.ag-ui.com/sdk/js/client/abstract-agent)
AbstractAgent 源码
1 | abstract run(input: RunAgentInput): Observable<BaseEvent>; |
httpAgent
[HttpAgent Api] (https://docs.ag-ui.com/sdk/js/client/http-agent)
httpAgent 基于 abstractAgent 抽象类
httpAgent 会实现 run 函数,发起真正的http 请求
1 |
|
runHttpRequest
runHttpRequest 处理流数据 转成 HttpEventType 流
1 |
|
transformHttpEventStream
1 | export enum EventType { |
1 | /** |
parseSSEStream
1 | /** |
parseProtoStream
1 | /** |
为什么默认 copilotKit 实例不同动作 可以发送不同http path 请求

从官网文档中可以看出,默认的 copilotKit 实例不同动作会基于 basePath 发送不同的http path 请求
实际请求时确实从寻找agent, 链接agent 服务,到向agent 提问 都发送不同的http path 请求
原因:
useAgent() 函数会返回一个 ProxiedCopilotRuntimeAgent 对象
ProxiedCopilotRuntimeAgent 从httpAgent继承,
ProxiedCopilotRuntimeAgent 这个类会重新生成run 的请求url, 重写 connect 方法过程会指定,
1 | /** |































































































