ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Genkit Dart 智能体开发实战:从 defineAgent 到 remoteAgent 的完整指南

2026/9/13 21:18:56 拓冰建站 浏览量
Genkit Dart 智能体开发实战:从 defineAgent 到 remoteAgent 的完整指南 Genkit Dart 智能体开发实战从 defineAgent 到 remoteAgent 的完整指南【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills导读本文以 Genkit Dart SDK 的 Agent 体系为主线系统讲解如何在 Dart/Flutter 中构建持久化、多轮对话的 AI 智能体从共享Genkit实例的插件注册、ai.defineAgent定义智能体到服务端chat()对话、HTTP 部署shelfHandler再到remoteAgent客户端消费与 Flutter 集成最后深入客户端托管状态client-managed state这一无服务端存储的精简方案。读完本文你将掌握 Genkit Dart 智能体从定义、联调到跨语言部署的完整链路并能直接套用文中代码搭建自己的天气助手、编码助手或研究型 Agent。本文内容以 references/agents.md 为主体骨架并补充该仓库内genkit-dart技能包中 agents-sessions、agents-deployment、agents-human-in-the-loop、agents-multi-agent 等配套参考文档的细节形成一份可直接落地的实战指南。什么是 Genkit Dart 的 Agent在 SKILL.md 的定义中Genkit Dart 是一个为 Dart 提供统一 AI 接口的 SDK覆盖代码生成、结构化输出、工具Tools、流Flows与 AI 智能体Agents。其中Agent是构建在“提示词prompts 工具tools”之上的持久化多轮对话原语。与裸的ai.generate/ai.definePrompt循环相比一个 Agent 额外提供了五个核心能力Sessions会话多轮历史以**不可变快照snapshots**的形式追踪State状态类型化的会话状态消息 自定义数据 工件 artifactsInterrupts中断人在回路human-in-the-loop的暂停 / 恢复Branching分支可从任意快照派生fork一段对话Detaching分离在后台执行一轮对话并通过轮询获取结果。Genkit Dart 的 Agent 采用渐进式披露progressive disclosure的组织方式本文档覆盖“定义智能体、服务化部署、客户端托管状态无存储”这一最核心的起点而会话持久化、中断、分支、后台执行、自定义状态、工件、多智能体编排与高级自定义智能体等进阶主题分别由配套参考文档承接在文中相应位置给出索引。包划分服务端 API 来自package:genkit/genkit.dart浏览器 / HTTP 客户端来自package:genkit/client.dart。这是理解后续所有代码的前提——服务端与客户端是两套独立包通过统一的 HTTP 协议互联。环境准备注册共享 Genkit 实例在定义任何智能体之前先把所需插件注册到一个共享的Genkit实例上。retry与RetryPlugin随核心package:genkit/genkit.dart一起发布其余智能体中间件agents、filesystem、skills、toolApproval来自package:genkit_middleware。// genkit.dart — 共享实例 模型引用 import package:genkit/genkit.dart; import package:genkit_google_genai/genkit_google_genai.dart; /// 默认能力较强模型大多数智能体使用。 final ModelRef defaultModel googleAI.gemini(gemini-flash-latest); /// 用于辅助任务的快速/廉价模型。 final ModelRef liteModel googleAI.gemini(gemini-flash-lite-latest); final Genkit ai Genkit( plugins: [ googleAI(), RetryPlugin(), ], model: defaultModel, );这里的ModelRef是模型引用类型defaultModel指向gemini-flash-latest适合承担智能体主体推理liteModel指向gemini-flash-lite-latest可用于问题分解、摘要等辅助任务在 agents-custom 的多步研究智能体示例中分解步骤就使用了liteModel。plugins中除模型插件外还注册了RetryPlugin()它与retry()中间件配套为智能体回合turn提供瞬态模型错误自动重试能力。后续所有示例都假定存在这样一个genkit.dart文件并统一使用其中的ai实例、defaultModel与liteModel。若要为智能体接入更多中间件如FilesystemPlugin()、SkillsPlugin()、ToolApprovalPlugin()也都在此处集中注册详见后文“智能体与中间件协同”一节。定义第一个智能体defineAgent 全解ai.defineAgent将提示词 工具配置 可选的会话存储合并注册为一个独立 action。下面是最完整的天气助手示例import package:genkit/genkit.dart; import package:schemantic/schemantic.dart; import genkit.dart; part weather_agent.g.dart; Schema() abstract class $GetWeatherInput { String get location; } Schema() abstract class $GetWeatherOutput { String get weather; String get temperature; } final getWeather ai.defineTool( name: getWeather, description: Get the current weather for a given location., inputSchema: GetWeatherInput.$schema, outputSchema: GetWeatherOutput.$schema, fn: (input, _) async GetWeatherOutput( weather: Sunny in ${input.location}, temperature: 71F, ), ); final weatherAgent ai.defineAgent( name: weatherAgent, system: You are a helpful weather assistant. Use the getWeather tool. Be concise., tools: [getWeather], use: [retry()], store: InMemorySessionStore(), );schemantic类型化 schema 的关键示例中的Schema()注解、.$schema静态属性以及$前缀的抽象类均来自schemantic库。part weather_agent.g.dart声明了由代码生成器产出的 part 文件——这是 Genkit Dart 实现类型安全的关键机制。SKILL.md 明确将其列为“关键技能CRITICAL skill”每当你遇到Schema()、SchemanticType或带$前缀的类就意味着正在使用 schemantic 的类型安全生成代码。详细用法参见 references/schemantic.md。defineAgent 常用选项选项说明name必填action 名称注册到 Genkit 注册表description面向编排者orchestrator的说明用于多智能体委派决策见 agents-multi-agentsystem/prompt提示词模板语义与definePrompt一致tools智能体可用的工具与中断工具interrupt-toolsmodel覆盖默认模型例如model: liteModeluse叠加在回合上的中间件retry()、filesystem(...)等store服务端持久化的SessionStore见 agents-sessionsstateSchema描述自定义会话状态的SchemanticTypeStatemaxTurns限制工具调用循环次数例如maxTurns: 30提示SKILL.md 中给出了一条选型建议——如果任务是对话式、多轮或描述为“agent / assistant / chatbot”应当使用ai.defineAgent而不是在 flow 里手搓generate tools 循环只有单次、无状态的生成才适合纯 flow。智能体与中间件协同一行一行地叠加复杂能力Agent 与 middleware 是天生一对use: [...]数组就是“无侵入叠加高级行为”的挂载点——子智能体委派、文件系统访问、技能加载、工具审批、重试每一样都只是一行配置。下面是一个叠加了工具审批、沙箱文件系统、技能加载与自动重试的编码助手import package:genkit/genkit.dart; import package:genkit_middleware/filesystem.dart; import package:genkit_middleware/skills.dart; import package:genkit_middleware/tool_approval.dart; import genkit.dart; final codingAgent ai.defineAgent( name: codingAgent, system: You are an expert AI coding assistant working in a sandboxed workspace., tools: [runShell, askUser], // 你自己的自定义工具/中断 use: [ // 在危险工具执行前要求用户审批中断只读/运行类工具自动放行。 // 顺序很重要toolApproval 要放在 filesystem 之前。 toolApproval( approved: [list_files, read_file, use_skill, run_shell, ask_user], ), // list_files / read_file / write_file / search_and_replace沙箱化。 filesystem(rootDirectory: workspaceDir), // 按需通过 use_skill 工具加载编码规范。 skills(skillPaths: [skillsDir]), // 对瞬态模型错误自动重试。 retry(), ], store: InMemorySessionStore(), // 工具审批需要 store maxTurns: 30, );关键约束必须在Genkit实例上注册对应的插件FilesystemPlugin()、SkillsPlugin()、ToolApprovalPlugin()、RetryPlugin()use: [...]中的引用才能在运行时解析。各中间件的初始化参数与行为详见 genkit_middleware.md。服务端对话agent.chat() 与回合流转agent.chat()开启一段对话。一个chat会在多轮之间自动携带状态。final chat weatherAgent.chat(); // 非流式回合 final res await chat.send(text: Weather in Tokyo?); print(res.text); print(res.snapshotId); // 本回合的不可变检查点 id // 追问回合——历史自动携带 final res2 await chat.send(text: What about Paris?); // 流式回合 final turn chat.sendStream(text: And London?); await for (final chunk in turn.stream) { stdout.write(chunk.text); } final finalRes await turn.response;每次send都会产生一个snapshotId它是“本回合的不可变检查点”标识。在配置了store的场景下快照链snapshot chain正是对话状态前进的载体即使是无 store 的客户端托管状态模式snapshotId也作为客户端追踪状态的依据。每回合环境上下文per-turn ambient contextsend、sendStream和detach都接受一个可选的context映射——回合级的环境数据认证信息、请求元数据等工具可通过ctx.context读取自定义智能体则通过options.context读取。final res await chat.send( text: What can I do?, context: { auth: {name: Ada, tier: pro}, }, );重要限制context仅适用于进程内in-process传输。remoteAgentHTTP传输会对非空context抛出UnsupportedError——远程智能体的 context 由服务端从 HTTP 请求headers/auth中派生所以客户端不要传入。用 CLI 验证智能体flow:run 的正确姿势genkit flow:run只运行 flow不运行 agent因此不能直接对ai.defineAgent执行flow:run。若要从 CLI 演练智能体例如一次快速、自终止的检查把一轮对话包进一个临时 flow然后运行它final tryWeatherAgent ai.defineFlow( name: tryWeatherAgent, fn: (String message, _) async (await weatherAgent.chat().send(text: message)).text, ); // genkit flow:run tryWeatherAgent Weather in Tokyo? -- dart run main.dart这正是 SKILL.md 推荐的 CLI 工作流flow:run是自终止的——运行一次、打印 Trace ID、随即退出适合非交互式快速验证而genkit start -- dart run main.dart则会持续运行并捕获每个 Genkit action 的 trace适合本地开发调试。CLI 的完整安装与用法genkit start、flow:run、trace:list/trace:get等见 SKILL.md。HTTP 服务化部署shelfHandler 与三个 action使用package:genkit_shelf的shelfHandler暴露智能体。每个Agent暴露三个 action对应三个 HTTP 端点agent.action→POST /api/name主回合turn端点agent.getSnapshotDataAction→POST /api/name/getSnapshot读取快照状态快照恢复 / 分支 / 后台轮询需要agent.abortAgentAction→POST /api/name/abort取消后台回合。import package:genkit_shelf/genkit_shelf.dart; import package:shelf_router/shelf_router.dart; final router Router(); // 主回合端点 router.post(/api/weatherAgent, shelfHandler(weatherAgent.action)); // 可选配套端点快照恢复 / 分支 / 后台 router.post( /api/weatherAgent/getSnapshot, shelfHandler(weatherAgent.getSnapshotDataAction), ); router.post( /api/weatherAgent/abort, shelfHandler(weatherAgent.abortAgentAction), );这三个路径与remoteAgent客户端的默认值${url}/getSnapshot、${url}/abort完全一致因此客户端只需提供基础url。wire body 与 Genkit 客户端协议一致{ data: input, init: init }。多智能体部署与 mountAgent 辅助函数当服务多个智能体时可以用一个辅助函数保持注册一致性来自 agents-deploymentimport package:genkit/genkit.dart; import package:genkit_shelf/genkit_shelf.dart; import package:shelf_router/shelf_router.dart; import package:agents_sample/weather_agent.dart; import package:agents_sample/background_agent.dart; /// 挂载智能体的回合 action 以及它的 /getSnapshot 与 /abort action。 void mountAgent(Router router, String path, Agent agent) { router.post(/api/$path, shelfHandler(agent.action)); router.post(/api/$path/getSnapshot, shelfHandler(agent.getSnapshotDataAction)); router.post(/api/$path/abort, shelfHandler(agent.abortAgentAction)); } final router Router(); mountAgent(router, weatherAgent, weatherAgent); mountAgent(router, backgroundAgent, backgroundAgent); // 客户端托管状态无状态智能体只需回合 action router.post( /api/weatherAgentStateless, shelfHandler(weatherAgentStateless.action), );不同能力需要暴露哪些配套端点可参考下表智能体能力getSnapshotabort普通对话客户端或服务端状态––快照恢复 / 分支✓–后台执行 / detach✓✓浏览器客户端的 CORS浏览器端的remoteAgent跨源调用例如 Jaspr / Flutter Web 开发服务器在不同端口需要 CORS。流式传输要求放行X-Genkit-Stream-Id头。可使用shelf_cors_headersimport dart:io; import package:shelf/shelf.dart; import package:shelf/shelf_io.dart as io; import package:shelf_cors_headers/shelf_cors_headers.dart; final handler const Pipeline() .addMiddleware(logRequests()) .addMiddleware( corsHeaders( headers: { Access-Control-Allow-Origin: *, Access-Control-Allow-Headers: Content-Type, Accept, X-Genkit-Stream-Id, Access-Control-Allow-Methods: GET, POST, OPTIONS, }, ), ) .addHandler(router.call); final port int.tryParse(Platform.environment[PORT] ?? ) ?? 8080; final server await io.serve(handler, InternetAddress.anyIPv4, port); print(Agents API server running on http://localhost:${server.port});注册时机提示Agent 在其定义处的顶层final被求值时注册进 Genkit。因此服务端bin/server.dart必须 import 并引用定义智能体的模块例如mountAgent(...)的调用defineAgent才会实际执行。多智能体、CORS、流式响应头以及完整服务器搭建的更多细节参见 agents-deployment.md。客户端消费remoteAgent 与跨语言后端浏览器 / Dart 客户端位于package:genkit/client.dart。remoteAgent返回一个类型化的 HTTP 客户端getSnapshotUrl/abortUrl默认取${url}/getSnapshot与${url}/abort。remoteAgent通过 HTTP 与任何 Genkit 智能体端点通信因此后端完全可互换——智能体可以是 Dart、JS/TypeScript 或 Go 实现的只要遵循同一套 wire 协议把url指向对应服务器即可。import package:genkit/client.dart; final weather remoteAgent(url: http://localhost:8080/api/weatherAgent); final chat weather.chat(); final turn chat.sendStream(text: Weather in Tokyo?); await for (final chunk in turn.stream) { stdout.write(chunk.text); } final res await turn.response; print(${res.snapshotId} ${chat.snapshotId} ${chat.state}); // 多轮——客户端自动携带状态前进 await chat.send(text: What about Paris?); // 错误以带 HTTP 风格状态码的 AgentError 形式暴露 try { await remoteAgent(url: $base/api/nope).chat().send(text: hi); } catch (err) { if (err is AgentError) print(err.status); }Flutter 集成认证头与生命周期客户端本身没有任何 Flutter 特性Flutter 应用与普通 Dart 程序一样使用package:genkit/client.dart的remoteAgent。真实应用中只有两件事值得注意——认证头auth headers与生命周期lifecycle。携带认证头headers参数用于附加每请求认证例如 Firebase / OAuth bearer token。它是FutureOrMapString, String? Function()类型因此可以异步执行且每个请求都会调用final agent remoteAgent( url: https://your-backend.example.com/api/weatherAgent, headers: () async { Authorization: Bearer ${await getIdToken()}, }, );生命周期管理在initState或 provider / 单例中只创建一次 agent用完后调用close()释放底层 HTTP 客户端。若想自行持有客户端传入httpClient:——此时客户端归调用方所有close()不会关闭它。一个最小流式聊天组件把turn.stream泵入 UIsetState再 awaitturn.responseimport package:flutter/material.dart; import package:genkit/client.dart; class ChatView extends StatefulWidget { const ChatView({super.key}); override StateChatView createState() _ChatViewState(); } class _ChatViewState extends StateChatView { late final AgentApi _agent remoteAgent( url: http://localhost:8080/api/weatherAgent, ); late final _chat _agent.chat(); var _reply ; override void dispose() { _agent.close(); // 释放 HTTP 客户端 super.dispose(); } Futurevoid _send(String text) async { setState(() _reply ); final turn _chat.sendStream(text: text); await for (final chunk in turn.stream) { setState(() _reply chunk.text); // 实时追加 token } await turn.response; // 最终 AgentResponse状态已由 _chat 追踪 } override Widget build(BuildContext context) Column( children: [ Expanded(child: SingleChildScrollView(child: Text(_reply))), TextField(onSubmitted: _send), ], ); }_chat实例会在多轮之间自动携带会话状态_chat.state、_chat.messages、_chat.snapshotId与服务端行为完全一致。SKILL.md 还提到几个 Dart 特有事项中断被建模为调用ctx.interrupt(...)的工具没有defineInterrupt子智能体委派使用package:genkit_middleware的agents()中间件且目前尚无artifacts()中间件需直接定义工件工具。中断、自定义状态与工件在 Flutter 中的工作方式与服务端完全相同。客户端托管状态无 store 的精简架构如果智能体没有store服务端就是完全无状态的会话状态 blob消息 自定义数据 工件由调用方持有。remoteAgent客户端会追踪它并在每一轮自动往返携带——不需要SessionStore也不需要管理快照 id。// 服务端不设 store → 无状态。客户端持有状态 blob。 final weatherAgentStateless ai.defineAgent( name: weatherAgentStateless, system: You are a helpful weather assistant. Use the getWeather tool. Be concise., tools: [getWeather], use: [retry()], );// 客户端复用同一个 chat状态自动线程化。 import package:genkit/client.dart; final agent remoteAgent(url: $base/api/weatherAgentStateless); final chat agent.chat(); await chat.send(text: Weather in London?); await chat.send(text: Is it sunny in Tokyo?); // 记住之前的回合 // 每轮之后可读取追踪到的状态 print(chat.state); print(chat.messages.length);选型建议当你不想运行服务端存储时使用客户端托管状态当服务端应持有历史记录或需要分支与后台执行时使用会话存储session store。中断两种模式均可工作。进阶地图Agent 能力的配套参考索引agents.md 是 Genkit Dart 智能体体系的入口文档其介绍的会话、状态、中断、分支、后台执行等能力在仓库中均有对应的深度参考按需取用Sessions persistenceSessionStore、InMemorySessionStore、FileSessionStore、FirestoreSessionStore。其中FirestoreSessionStore以增量 JSON Patch diff 分片检查点方式持久化每一轮可避免单文档逼近 Firestore 1 MiB 上限并让每轮读写次数受checkpointInterval默认 25约束而非会话总长度适合长生命周期对话 / 编码智能体。Human-in-the-loop / interrupts以工具调用实现控制流——中断工具调用ctx.interrupt(...)暂停回合然后通过chat.resume(respond: [...])从暂停点精确恢复Dart 中没有defineInterrupt。BranchingsnapshotId是不可变检查点类似 git commit通过agent.chat(snapshotId: ...)从同一快照派生多个独立时间线。Background agentschat.detach(...)立即返回带snapshotId的DetachedTask服务端后台处理完成后把快照更新为终止状态completed/failed/aborted/expired客户端task.poll()/task.abort()轮询与取消。Working with state通过stateSchema声明类型化自定义状态工具内用ai.currentSessionState()读取、session.updateCustom(...)写入客户端经customPatch分块实时同步。Artifacts会话内按名称去重的具名交付物文件、报告、代码等经session.addArtifacts()/getArtifacts()读写并作为流式artifact分块下发客户端。Multi-agent orchestrationagents()中间件为编排者注入delegate_to_name委派工具并支持maxDelegations防失控与artifactStrategy控制子智能体工件的合并方式。Advanced custom agentsdefineCustomAgent让你完全掌控回合——多次模型调用、自定义编排逻辑、手动消息/状态管理以及options.sendChunk(...)的定制进度流。Deploying agents基于genkit_shelf的多智能体 HTTP 服务化、CORS 与浏览器流式头配置。最佳实践小结综合 SKILL.md 与本文档落地 Genkit Dart 智能体时建议遵循以下原则Agent 还是 flow任务若为对话式、多轮或可描述为“agent / assistant / chatbot”用ai.defineAgent而非在 flow 内手搓循环纯单次、无状态生成才用 flow。先dart analyze再交付生成最终代码前确保干净编译——schemantic 的.g.dart生成代码是类型安全的基石。用 Genkit CLI 本地调试genkit start -- dart run main.dart捕获每个 action 的 trace用trace:list/trace:get验证工具是否真实被调用非交互场景用flow:run自终止智能体则包一层临时 flow 调用。状态归属要清晰服务端拥有历史、需要分支或后台执行时配store否则走客户端托管状态省去服务端存储。中间件按需叠加工具审批、沙箱文件系统、技能加载、自动重试都是use: [...]的一行配置但务必同步在Genkit实例上注册对应插件。至此从defineAgent定义、chat()对话、shelfHandler部署到remoteAgent/ Flutter 消费的完整闭环已经打通结合配套参考文档你可以继续深入会话持久化、人在回路审批、对话分支、后台任务与多智能体编排等进阶能力。【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考