
在 Angular 中集成 A2UI 与 A2A 协议Restaurant Finder 示例应用从零到运行【免费下载链接】a2ui项目地址: https://gitcode.com/GitHub_Trending/a2/a2ui本篇指南基于 A2UI 仓库中的 Angular 示例应用完整讲解如何在本机搭建并运行一个「Agent 后端 Angular 前端」的 A2UI 客户端你将掌握yarn工作区构建、Gemini API Key 配置、A2A 协议客户端接入、SSE 流式渲染开关以及将 Agent 返回的 UI 消息交给 Angular 渲染器实时绘制的完整链路并理解在非可信 Agent 场景下必须落实的安全基线。示例应用架构概览Restaurant Finder餐厅查找示例由两个独立进程组成二者通过 A2AAgent-to-Agent协议通信Agent 后端位于 samples/agent/adk/restaurant_finder是一个基于 Python 的 ADK AgentA2A 服务端运行在http://localhost:10002负责接收用户查询、调用 LLM默认 Gemini并生成包含 A2UI 消息如卡片、按钮、文本等的响应。Angular 前端位于 samples/client/angular是一个 Angular 21 应用restaurant工程运行在http://localhost:4200。它一方面作为 A2A 客户端向 Agent 发送请求另一方面通过a2ui/angular渲染库把 Agent 返回的 A2UI 消息渲染成真实 UI。从 angular.json 可以看到这个 Angular 工作区同时包含两个工程libA2UI Angular 渲染库自身的打包工程和restaurant示例应用本体。restaurant使用 Angular SSRangular/ssr其服务端入口 server.ts 承担了 A2A 客户端代理的关键职责这一点会在下文展开。环境准备Prerequisites运行示例需要两样基础工具Node.jsAngular 工程与yarn构建所需建议使用较新的 LTS 版本。uvPython 包管理器与运行器用于启动 Restaurant Finder Agent 后端。安装方式见 uv 官方文档https://docs.astral.sh/uv/getting-started/installation/。此外由于 Agent 依赖 Google 生成式 AI 能力你还需要一个Gemini API Key可在 Google AI Studio 获取或改用 Vertex AI详见后文.env配置。安装与构建依赖在仓库根目录执行以下命令安装全部工作区依赖并构建所有包包括a2ui/web_core、a2ui/markdown-it、a2ui/angular等 workspace 内部包yarn install yarn build:all这一步是必须的restaurant工程通过workspace:*协议依赖 package.json 中声明的a2ui/angular、a2ui/web_core、a2ui/markdown-it只有先构建这些本地包Angular 才能正确解析导入。仓库根目录的 package.json 与yarn.lock共同维护了这些 workspace 依赖关系。配置 Gemini API KeyAgent 后端需要读取 API Key 才能调用 LLM。从仓库根目录执行cd samples/client/angular cp ../../agent/adk/restaurant_finder/.env.example ../../agent/adk/restaurant_finder/.env然后编辑.env填入你的真实 Key。.env文件已被 gitignore不会进入版本控制这是出于安全考虑的标准做法。[.env.example](https://link.gitcode.com/i/0e7038bcc690cb803bbdddd7535715b0)的内容如下# Copy this file to .env and fill in your API key # Get your API key at: https://aistudio.google.com/apikey GEMINI_API_KEYyour_gemini_api_key_here # Optional: Use Vertex AI instead of Gemini API # GOOGLE_GENAI_USE_VERTEXAITRUE可以看到两个可选配置项配置项作用备注GEMINI_API_KEY使用 Gemini API 时的认证凭据必填替换占位符即可GOOGLE_GENAI_USE_VERTEXAI切换为 Vertex AI 方式调用可选设为TRUE后需额外配置云凭据启动双端服务示例需要两个独立终端分别启动后端与前端。终端 1启动 Agent 后端cd samples/agent/adk/restaurant_finder uv run .启动成功后Agent 会作为 A2A 服务端监听http://localhost:10002并对外暴露其 AgentCardhttp://localhost:10002/.well-known/agent-card.json供客户端发现其能力与消息接口。终端 2启动 Angular 前端cd samples/client/angular yarn start restaurant该命令执行ng serve见 package.json 中的start: ng serve开发服务器默认监听http://localhost:4200。打开终端输出的 URL通常就是http://localhost:4200你会看到 Restaurant Finder 的搜索界面输入类似 “Top 5 Chinese restaurants in New York.” 的查询即可体验完整流程。如果你希望一条命令同时拉起 Agent 与前端仓库还提供了demo:restaurant脚本它借助concurrently并行启动两个进程并分色输出日志yarn workspace angular-a2ui demo:restaurant即 package.json 中的demo:restaurant: yarn build:renderer concurrently -k -n \AGENT,WEB\ ...。数据流解析请求如何从 Angular 到达 Agent 并回流渲染理解这条链路有助于你把示例改造成自己的应用。整个流程分为「服务端代理」与「浏览器端消费」两段。服务端/a2a中间件与 A2A 客户端server.ts 用 Express 注册了一个POST /a2a路由浏览器不直接连接 Agent而是把请求发给同源的 SSR 服务端由服务端作为 A2A 客户端转发解析请求体根据内容区分三种输入——携带event的 A2UI 事件消息、携带query的文本查询、以及兼容旧版的裸 JSON 事件。文本查询被包装为{kind: text, text}的 A2A PartA2UI 事件则被包装为{kind: data, data, metadata: {mimeType: application/a2uijson}}的 Part携带contextId以维持多轮会话上下文。创建 A2A 客户端createOrGetClient()通过A2AClient.fromCardUrl(http://localhost:10002/.well-known/agent-card.json, ...)从 AgentCard 发现 Agent 的消息端点并注入自定义fetchImpl——它在请求头中附加X-A2A-Extensions: https://a2ui.org/a2a-extension/a2ui/v0.9向 Agent 声明本客户端支持 A2UI 扩展能力。发送并转发响应根据流式开关调用sendMessageStream或sendMessage再将 Agent 返回的消息 Parts 以 JSON或 SSE形式回传浏览器。浏览器端Client 服务与 SSE 消费client.ts 中名为Client的 Angular 服务封装了前端到服务端代理的请求makeRequest()向/a2a发起POST并在每次交互前清空renderer.surfaceGroup中已有的 surface保证新回复替换旧界面。根据响应头的content-type分流text/event-stream走handleStreamingResponse()否则走handleNonStreamingResponse()。流式分支用ReadableStreamTextDecoder逐块解析data: json\n\n格式的 SSE 帧并记录contextId供后续轮次使用。解析出的parts经processParts()过滤掉纯文本 Partkind text将其余消息交给A2uiRendererService.processMessages()渲染。渲染层Renderer、Surface 与 BasicCatalog应用在 app.config.ts 中通过provideA2Ui(...)完成渲染器装配provideA2Ui(() { const injector inject(Injector); return { catalogs: [new BasicCatalog()], actionHandler: (action: A2uiClientAction) injector.get(Client).handleAction(action), }; }), provideMarkdownRenderer(renderMarkdown as any),catalogs: [new BasicCatalog()]注册 A2UI Basic Catalog按钮、卡片、输入框、列表等标准组件这些组件在 v0_9/catalog/basic 下有完整的 Angular 组件实现与单元测试。actionHandler把用户在 Agent 生成的界面上触发的动作如点击按钮回传给Client从而形成「用户操作 → Agent → 新 UI → 再次渲染」的闭环。provideMarkdownRenderer注入由a2ui/markdown-it提供的 Markdown 渲染能力使Text组件支持富文本。应用模板 app.html 中通过a2ui-v09-surface [surfaceId]entry[0] /即SurfaceComponent为每个 surface 创建渲染挂载点并通过if (client.isLoading() surfaces.size 0)展示加载动画。app.ts 中的handleSubmit()捕获表单提交、调用client.makeRequest()并驱动一组轮换的 loading 文案。流式与非流式ENABLE_STREAMING 开关默认情况下Angular 客户端使用流式 API与 Agent 通信——Agent 分多次推送消息任务状态更新、制品更新前端边收边渲染用户能实时看到界面逐步构建体验更接近 LLM 的逐字输出。如需关闭流式设置环境变量ENABLE_STREAMINGfalse后重启前端export ENABLE_STREAMINGfalse yarn start restaurant开关的实现位置在 server.tsconst enableStreaming process.env[ENABLE_STREAMING] ! false;即只要环境变量不是字符串false就启用流式。流式模式下服务端把 A2A 的task/status-update/artifact-update事件中携带的 Parts 以data: {...}\n\n逐帧写入 SSE 响应并显式设置Cache-Control: no-cache、Connection: keep-alive、X-Accel-Buffering: no禁用代理层缓冲保证事件实时到达非流式模式则直接await client.sendMessage(...)拿到完整 Task 后一次性返回{parts, contextId}JSON并设置Cache-Control: no-store。主题定制让 Agent 生成的界面贴合你的品牌示例展示了 A2UI 主题系统的一种落地方式。theme.ts 导出一个Types.Theme对象它包含elements对原生 HTML 元素a、button、input、p、textarea、video等的样式映射键名是 A2UI 样式 token如typography-f-sf、border-br-16、color-bgc-s30配合a2ui/web_core/styles的Styles.merge组合出明暗两套样式components对 Basic Catalog 组件Button、Card、TextField、Modal、CheckBox等及其内部子元素container、label、element、backdrop的样式覆盖additionalStyles追加自定义 CSS 属性与渐变、阴影等视觉增强例如示例中为Button定义了渐变背景为Text的标题定义了文字渐变裁剪markdown指定 Markdown 渲染元素继承的样式 token。示例中App组件还提供了明暗主题切换按钮toggleTheme依据window.getComputedStyle的colorScheme切换body上的light/darkclass配合light-dark()CSS 函数实现自适应配色。安全注意事项务必阅读README 明确强调示例代码仅用于演示 A2UI 与 A2A 协议的机制在生产环境中任何不受你直接控制的 Agent 都应被视为潜在不可信实体。具体风险包括Prompt 注入恶意 Agent 可能在 AgentCard、消息、制品或任务状态中携带精心构造的数据如name、skills.description字段。若未经净化就拼接进提示词喂给 LLM可能让应用暴露于提示注入攻击。界面欺骗PhishingAgent 下发的 UI 定义与数据流同样不可信恶意 Agent 可能伪造看似合法的界面欺骗用户。脚本注入XSS属性值中的恶意脚本可能被注入页面执行。拒绝服务DoS攻击者可下发复杂度极高的布局拖垮客户端性能。嵌入式内容风险如果应用支持 iframe / WebView 等可选嵌入式内容还需严防被导向恶意外部站点。因此生产实现必须由开发者落实相应的安全措施包括但不限于输入净化sanitization、Content Security PolicyCSP、对嵌入式内容的严格隔离、以及安全的凭据管理。这也是在 server.ts 中通过X-A2A-Extensions声明协议能力之外工程上需要额外补齐的一环。小结通过本示例你可以掌握一条完整的 A2UI 客户端实践路径从yarn工作区构建、.env密钥配置、双进程启动到 SSR 服务端 A2A 代理、浏览器端 SSE 消费、provideA2Ui BasicCatalog 渲染装配再到ENABLE_STREAMING流式开关与主题定制。进一步地仓库中的渲染库源码如 renderers/angular 与 projects/lib/src/v0_9 下的组件与测试可作为你扩展自定义组件、理解消息处理细节的参考而官方文档 docs/public/guides 中的相关指南则提供了更系统化的 A2UI 概念讲解。【免费下载链接】a2ui项目地址: https://gitcode.com/GitHub_Trending/a2/a2ui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考