[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-inngest--agent-kit":3,"tool-inngest--agent-kit":64},[4,17,27,35,43,56],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":16},3808,"stable-diffusion-webui","AUTOMATIC1111\u002Fstable-diffusion-webui","stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面，旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点，将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。\n\n无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师，还是想要深入探索模型潜力的开发者与研究人员，都能从中获益。其核心亮点在于极高的功能丰富度：不仅支持文生图、图生图、局部重绘（Inpainting）和外绘（Outpainting）等基础模式，还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外，它内置了 GFPGAN 和 CodeFormer 等人脸修复工具，支持多种神经网络放大算法，并允许用户通过插件系统无限扩展能力。即使是显存有限的设备，stable-diffusion-webui 也提供了相应的优化选项，让高质量的 AI 艺术创作变得触手可及。",162132,3,"2026-04-05T11:01:52",[13,14,15],"开发框架","图像","Agent","ready",{"id":18,"name":19,"github_repo":20,"description_zh":21,"stars":22,"difficulty_score":23,"last_commit_at":24,"category_tags":25,"status":16},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",138956,2,"2026-04-05T11:33:21",[13,15,26],"语言模型",{"id":28,"name":29,"github_repo":30,"description_zh":31,"stars":32,"difficulty_score":23,"last_commit_at":33,"category_tags":34,"status":16},2271,"ComfyUI","Comfy-Org\u002FComfyUI","ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎，专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式，采用直观的节点式流程图界面，让用户通过连接不同的功能模块即可构建个性化的生成管线。\n\n这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景，也能自由组合模型、调整参数并实时预览效果，轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性，不仅支持 Windows、macOS 和 Linux 全平台，还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构，并率先支持 SDXL、Flux、SD3 等前沿模型。\n\n无论是希望深入探索算法潜力的研究人员和开发者，还是追求极致创作自由度的设计师与资深 AI 绘画爱好者，ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能，使其成为当前最灵活、生态最丰富的开源扩散模型工具之一，帮助用户将创意高效转化为现实。",107662,"2026-04-03T11:11:01",[13,14,15],{"id":36,"name":37,"github_repo":38,"description_zh":39,"stars":40,"difficulty_score":23,"last_commit_at":41,"category_tags":42,"status":16},3704,"NextChat","ChatGPTNextWeb\u002FNextChat","NextChat 是一款轻量且极速的 AI 助手，旨在为用户提供流畅、跨平台的大模型交互体验。它完美解决了用户在多设备间切换时难以保持对话连续性，以及面对众多 AI 模型不知如何统一管理的痛点。无论是日常办公、学习辅助还是创意激发，NextChat 都能让用户随时随地通过网页、iOS、Android、Windows、MacOS 或 Linux 端无缝接入智能服务。\n\n这款工具非常适合普通用户、学生、职场人士以及需要私有化部署的企业团队使用。对于开发者而言，它也提供了便捷的自托管方案，支持一键部署到 Vercel 或 Zeabur 等平台。\n\nNextChat 的核心亮点在于其广泛的模型兼容性，原生支持 Claude、DeepSeek、GPT-4 及 Gemini Pro 等主流大模型，让用户在一个界面即可自由切换不同 AI 能力。此外，它还率先支持 MCP（Model Context Protocol）协议，增强了上下文处理能力。针对企业用户，NextChat 提供专业版解决方案，具备品牌定制、细粒度权限控制、内部知识库整合及安全审计等功能，满足公司对数据隐私和个性化管理的高标准要求。",87618,"2026-04-05T07:20:52",[13,26],{"id":44,"name":45,"github_repo":46,"description_zh":47,"stars":48,"difficulty_score":23,"last_commit_at":49,"category_tags":50,"status":16},2268,"ML-For-Beginners","microsoft\u002FML-For-Beginners","ML-For-Beginners 是由微软推出的一套系统化机器学习入门课程，旨在帮助零基础用户轻松掌握经典机器学习知识。这套课程将学习路径规划为 12 周，包含 26 节精炼课程和 52 道配套测验，内容涵盖从基础概念到实际应用的完整流程，有效解决了初学者面对庞大知识体系时无从下手、缺乏结构化指导的痛点。\n\n无论是希望转型的开发者、需要补充算法背景的研究人员，还是对人工智能充满好奇的普通爱好者，都能从中受益。课程不仅提供了清晰的理论讲解，还强调动手实践，让用户在循序渐进中建立扎实的技能基础。其独特的亮点在于强大的多语言支持，通过自动化机制提供了包括简体中文在内的 50 多种语言版本，极大地降低了全球不同背景用户的学习门槛。此外，项目采用开源协作模式，社区活跃且内容持续更新，确保学习者能获取前沿且准确的技术资讯。如果你正寻找一条清晰、友好且专业的机器学习入门之路，ML-For-Beginners 将是理想的起点。",84991,"2026-04-05T10:45:23",[14,51,52,53,15,54,26,13,55],"数据工具","视频","插件","其他","音频",{"id":57,"name":58,"github_repo":59,"description_zh":60,"stars":61,"difficulty_score":10,"last_commit_at":62,"category_tags":63,"status":16},3128,"ragflow","infiniflow\u002Fragflow","RAGFlow 是一款领先的开源检索增强生成（RAG）引擎，旨在为大语言模型构建更精准、可靠的上下文层。它巧妙地将前沿的 RAG 技术与智能体（Agent）能力相结合，不仅支持从各类文档中高效提取知识，还能让模型基于这些知识进行逻辑推理和任务执行。\n\n在大模型应用中，幻觉问题和知识滞后是常见痛点。RAGFlow 通过深度解析复杂文档结构（如表格、图表及混合排版），显著提升了信息检索的准确度，从而有效减少模型“胡编乱造”的现象，确保回答既有据可依又具备时效性。其内置的智能体机制更进一步，使系统不仅能回答问题，还能自主规划步骤解决复杂问题。\n\n这款工具特别适合开发者、企业技术团队以及 AI 研究人员使用。无论是希望快速搭建私有知识库问答系统，还是致力于探索大模型在垂直领域落地的创新者，都能从中受益。RAGFlow 提供了可视化的工作流编排界面和灵活的 API 接口，既降低了非算法背景用户的上手门槛，也满足了专业开发者对系统深度定制的需求。作为基于 Apache 2.0 协议开源的项目，它正成为连接通用大模型与行业专有知识之间的重要桥梁。",77062,"2026-04-04T04:44:48",[15,14,13,26,54],{"id":65,"github_repo":66,"name":67,"description_en":68,"description_zh":69,"ai_summary_zh":69,"readme_en":70,"readme_zh":71,"quickstart_zh":72,"use_case_zh":73,"hero_image_url":74,"owner_login":75,"owner_name":76,"owner_avatar_url":77,"owner_bio":78,"owner_company":79,"owner_location":79,"owner_email":80,"owner_twitter":75,"owner_website":81,"owner_url":82,"languages":83,"stars":92,"forks":93,"last_commit_at":94,"license":95,"difficulty_score":23,"env_os":96,"env_gpu":96,"env_ram":96,"env_deps":97,"category_tags":104,"github_topics":105,"view_count":23,"oss_zip_url":79,"oss_zip_packed_at":79,"status":16,"created_at":111,"updated_at":112,"faqs":113,"releases":143},3067,"inngest\u002Fagent-kit","agent-kit","AgentKit: Build multi-agent networks in TypeScript with deterministic routing and rich tooling via MCP.","AgentKit 是一款基于 TypeScript 构建的开源框架，旨在帮助开发者轻松创建由多个智能体（Agent）协作组成的复杂网络。它主要解决了多智能体系统中路由逻辑难以控制、工具集成繁琐以及状态管理混乱等痛点，让智能体之间的协作更加确定且灵活。\n\n这款工具特别适合熟悉 TypeScript 的 AI 应用开发者使用。其核心亮点在于引入了“确定性路由”机制，允许通过代码或大模型（如 ReAct 模式）精确控制智能体的流转逻辑；同时深度集成了 MCP（模型上下文协议），能够无缝连接丰富的外部工具和服务。此外，AgentKit 内置了完整的状态机和追踪系统，结合 Inngest 编排引擎，不仅支持本地调试，还能确保应用在云端部署时具备容错能力，大幅降低了构建高可靠性多智能体应用的门槛。","# AgentKit\n\n_Build multi-agent networks with deterministic routing and rich tooling via MCP._\n\n![AgentKit Tracing](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Finngest_agent-kit_readme_26896112baba.png)\n\n\u003Cp align=\"center\">\n    \u003Ca href=\"https:\u002F\u002Fagentkit.inngest.com\u002Foverview\">Documentation\u003C\u002Fa>\n    \u003Cspan>&nbsp;·&nbsp;\u003C\u002Fspan>\n    \u003Ca href=\"https:\u002F\u002Fwww.inngest.com\u002Fblog?ref=github-agent-kit-readme\">Blog\u003C\u002Fa>\n    \u003Cspan>&nbsp;·&nbsp;\u003C\u002Fspan>\n    \u003Ca href=\"https:\u002F\u002Fwww.inngest.com\u002Fdiscord\">Community\u003C\u002Fa>\n\u003C\u002Fp>\n\nAgentKit offers more deterministic and flexible routing, works with multiple model providers, embraces MCP (for rich tooling), and supports the unstoppable and growing community of TypeScript AI developers. Combined the Inngest Dev Server to start locally and its orchestration engine, making your Agents fault-tolerant when deployed to the cloud.\n\n**Core concepts**\n\n- [**Agents**](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Fagents): LLM calls that can be combined with prompts, [tools](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Ftools), and [MCP](https:\u002F\u002Fagentkit.inngest.com\u002Fadvanced-patterns\u002Fmcp).\n- [**Networks**](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Fnetworks): a simple way to get Agents to collaborate with a shared State, including handoff.\n- [**State**](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Fstate): combines conversation history with a fully typed state machine, used in routing.\n- [**Routers**](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Frouters): where the autonomy lives, from code-based to LLM-based (ex: ReAct) orchestration\n- [**Tracing**](https:\u002F\u002Fagentkit.inngest.com\u002Fgetting-started\u002Flocal-development): debug and optimize your workflow locally and in the cloud with built-in tracing\n\nGet started now by [cloning our examples](https:\u002F\u002Fagentkit.inngest.com\u002Fexamples\u002Foverview) or [exploring the documentation](https:\u002F\u002Fagentkit.inngest.com\u002Foverview).\n\n## Get started\n\n```tsx\nnpm i @inngest\u002Fagent-kit inngest\n```\n\n**Note:** Starting with AgentKit v0.9.0, you need to install `inngest` as a separate dependency alongside `@inngest\u002Fagent-kit`. This ensures proper runtime compatibility and prevents conflicts when multiple packages depend on different versions of Inngest.\n\n## MCP Agent example\n\nChoose your favorite MCP server on Smithery (or self-host one) to build an AgentKit Agent using MCP as tools. Here is an example using the [Neon database MCP server](https:\u002F\u002Fsmithery.ai\u002Fserver\u002Fneon):\n\n```tsx\nimport {\n  anthropic,\n  createAgent,\n  createNetwork,\n  createTool,\n} from \"@inngest\u002Fagent-kit\";\nimport { createServer } from \"@inngest\u002Fagent-kit\u002Fserver\";\nimport { createSmitheryUrl } from \"@smithery\u002Fsdk\u002Fconfig.js\";\nimport { z } from \"zod\";\n\nconst neonServerUrl = createSmitheryUrl(\n  \"https:\u002F\u002Fserver.smithery.ai\u002Fneon\u002Fmcp?profile=bored-catshark-da8hf&api_key=123123123\"\n);\n\nconst neonAgent = createAgent({\n  name: \"neon-agent\",\n  system: `You are a helpful assistant that help manage a Neon account.\n  IMPORTANT: Call the 'done' tool when the question is answered.\n  `,\n  tools: [\n    createTool({\n      name: \"done\",\n      description: \"Call this tool when you are finished with the task.\",\n      parameters: z.object({\n        answer: z.string().describe(\"Answer to the user's question.\"),\n      }),\n      handler: async ({ answer }, { network }) => {\n        network?.state.kv.set(\"answer\", answer);\n      },\n    }),\n  ],\n  mcpServers: [\n    {\n      name: \"neon\",\n      transport: {\n        type: \"streamable-http\",\n        url: neonServerUrl.toString(),\n      },\n    },\n  ],\n});\n\nconst neonAgentNetwork = createNetwork({\n  name: \"neon-agent\",\n  agents: [neonAgent],\n  defaultModel: anthropic({\n    model: \"claude-3-5-sonnet-20240620\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  router: ({ network }) => {\n    if (!network?.state.kv.get(\"answer\")) {\n      return neonAgent;\n    }\n    return;\n  },\n});\n\n\u002F\u002F Create and start the server\nconst server = createServer({\n  networks: [neonAgentNetwork],\n});\n\nserver.listen(3010, () =>\n  console.log(\"Support Agent demo server is running on port 3010\")\n);\n```\n\nGet started with this example locally: [https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fmcp-neon-agent#readme](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fmcp-neon-agent#readme)\n\nYou will find other examples in the sections below.\n\n## Deterministic Routing with State-based routing\n\nAgentKit provides a unique approach to deterministic Routing with State-based routing that enables the implementation of code-based to fully autonomous routing while keeping control all along the way.\n\nThe State is a key value stored and shared between all the Agents of the same network.\n\nThis state is then accessible from the router, agent lifecycle callbacks, agent prompts, and agent tools:\n\n```mermaid\nflowchart LR\n\tsubgraph Network\n\t\tstate[\"State\"]\n\t\tsubgraph Agent\n\t\t\tsystemp[\"System prompt\"]\n\t\t\ttools[\"Tools\"]\n\t\t\tlifecycle[\"Lifecycle callbacks\"]\n\t\tend\n\t\trouter[\"Router\"]\n\tend\n\n\n\tstate-->systemp\n\tstate\u003C-->tools\n\tstate\u003C-->lifecycle\n\tstate\u003C-->router\n```\n\n_The bidirectional arrows illustrate an R\u002FW write access, while the one-way arrows have an R\u002FO access._\n\nThis shared State, combined with the network's message history, is the building block of AgentKit's deterministic stated-based routing.\n\n### Code-based routing\n\nWe recommend starting with a code-based routing that provides complete control over your network execution flow.\n\nThis routing pattern is the most deterministic. By providing a Routing function that gets access to the state and history, you will implement an agentic routing that reacts to the state updates performed by the Agents’ tools.\n\nHere is an example of a Coding Agent using a code-based router to orchestrate the agents of the network based on the plan generated by the `codeAssistantAgent`:\n\n```tsx\nimport { z } from \"zod\";\nimport {\n  anthropic,\n  createAgent,\n  createNetwork,\n  createTool,\n} from \"@inngest\u002Fagent-kit\";\n\nimport { readFileSync } from \"fs\";\nimport { join } from \"path\";\n\n\u002F\u002F create a shared tool\nconst saveSuggestions = createTool({\n  name: \"save_suggestions\",\n  description: \"Save the suggestions made by other agents into the state\",\n  parameters: z.object({\n    suggestions: z.array(z.string()),\n  }),\n  handler: async (input, { network }) => {\n    const suggestions = network?.state.kv.get(\"suggestions\") || [];\n    network?.state.kv.set(\"suggestions\", [\n      ...suggestions,\n      ...input.suggestions,\n    ]);\n    return \"Suggestions saved!\";\n  },\n});\n\n\u002F\u002F create agents with access to the state via the `saveSuggestions` tool\nconst documentationAgent = createAgent({\n  name: \"documentation_agent\",\n  system: \"You are an expert at generating documentation for code\",\n  tools: [saveSuggestions],\n});\n\nconst analysisAgent = createAgent({\n  name: \"analysis_agent\",\n  system: \"You are an expert at analyzing code and suggesting improvements\",\n  tools: [saveSuggestions],\n});\n\nconst summarizationAgent = createAgent({\n  name: \"summarization_agent\",\n  system: ({ network }) => {\n    const suggestions = network?.state.kv.get(\"suggestions\") || [];\n    return `Save a summary of the following suggestions:\n    ${suggestions.join(\"\\n\")}`;\n  },\n  tools: [\n    createTool({\n      name: \"save_summary\",\n      description:\n        \"Save a summary of the suggestions made by other agents into the state\",\n      parameters: z.object({\n        summary: z.string(),\n      }),\n      handler: async (input, { network }) => {\n        network?.state.kv.set(\"summary\", input.summary);\n        return \"Saved!\";\n      },\n    }),\n  ],\n});\n\n\u002F\u002F Create the code assistant agent which generates a plan\nconst codeAssistantAgent = createAgent({\n  name: \"code_assistant_agent\",\n  system: ({ network }) => {\n    const agents = Array.from(network?.agents.values() || [])\n      .filter(\n        (agent) =>\n          ![\"code_assistant_agent\", \"summarization_agent\"].includes(agent.name)\n      )\n      .map((agent) => `${agent.name} (${agent.system})`);\n    return `From a given user request, ONLY perform the following tool calls:\n- read the file content\n- generate a plan of agents to run from the following list: ${agents.join(\", \")}\n\nAnswer with \"done\" when you are finished.`;\n  },\n  tools: [\n    createTool({\n      name: \"read_file\",\n      description: \"Read a file from the current directory\",\n      parameters: z.object({\n        filename: z.string(),\n      }),\n      handler: async (input, { network }) => {\n        const filePath = join(process.cwd(), `files\u002F${input.filename}`);\n        const code = readFileSync(filePath, \"utf-8\");\n        network?.state.kv.set(\"code\", code);\n        return \"File read!\";\n      },\n    }),\n    createTool({\n      name: \"generate_plan\",\n      description: \"Generate a plan of agents to run\",\n      parameters: z.object({\n        plan: z.array(z.string()),\n      }),\n      handler: async (input, { network }) => {\n        network?.state.kv.set(\"plan\", input.plan);\n        return \"Plan generated!\";\n      },\n    }),\n  ],\n});\n\nconst network = createNetwork({\n  name: \"code-assistant-v2\",\n  agents: [\n    codeAssistantAgent,\n    documentationAgent,\n    analysisAgent,\n    summarizationAgent,\n  ],\n  \u002F\u002F our routing function relies on the shared state to orchestrate agents\n  \u002F\u002F   first, the codeAssistantAgent is called and then, its plan gets\n  \u002F\u002F   executed step by step until a summary gets written in the state.\n  router: ({ network }) => {\n    if (!network?.state.kv.has(\"code\") || !network?.state.kv.has(\"plan\")) {\n      return codeAssistantAgent;\n    } else {\n      const plan = (network?.state.kv.get(\"plan\") || []) as string[];\n      const nextAgent = plan.pop();\n      if (nextAgent) {\n        network?.state.kv.set(\"plan\", plan);\n        return network?.agents.get(nextAgent);\n      } else if (!network?.state.kv.has(\"summary\")) {\n        return summarizationAgent;\n      } else {\n        return undefined;\n      }\n    }\n  },\n  defaultModel: anthropic({\n    model: \"claude-3-5-sonnet-latest\",\n    defaultParameters: {\n      max_tokens: 4096,\n    },\n  }),\n});\n```\n\nThe source code is available here: [https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fblob\u002Fmain\u002Fexamples\u002Fcode-assistant-agentic\u002Fsrc\u002Findex.ts](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fblob\u002Fmain\u002Fexamples\u002Fcode-assistant-agentic\u002Fsrc\u002Findex.ts)\n\n### Agent-based routing\n\nThe Agent-based routing replaces the routing function with an Agent. This enables your network of agents to autonomously select which agents to execute and decide when the tasks are completed.\n\nA Routing Agent comes with an `onRoute` lifecycle callback that recalls the code-based routing approach. This lifecycle callback is your gateway to keep control of the Agent routing decision.\n\nThe below example showcases a Support Agent using a Routing Agent as a “Supervisor”:\n\n```tsx\nimport {\n  anthropic,\n  createAgent,\n  createNetwork,\n  createRoutingAgent,\n  createTool,\n} from \"@inngest\u002Fagent-kit\";\nimport { z } from \"zod\";\n\nimport { isLastMessageOfType, lastResult } from \".\u002Futils.js\";\n\nimport { knowledgeBaseDB, releaseNotesDB, ticketsDB } from \".\u002Fdatabases.js\";\n\n\u002F\u002F Create shared tools\nconst searchKnowledgeBase = createTool({\n  name: \"search_knowledge_base\",\n  description: \"Search the knowledge base for relevant articles\",\n  parameters: z.object({\n    query: z.string().describe(\"The search query\"),\n  }),\n  handler: async ({ query }, { step }) => {\n    return await step?.run(\"search_knowledge_base\", async () => {\n      \u002F\u002F Simulate knowledge base search\n      const results = knowledgeBaseDB.filter(\n        (article) =>\n          article.title.toLowerCase().includes(query.toLowerCase()) ||\n          article.content.toLowerCase().includes(query.toLowerCase())\n      );\n      return results;\n    });\n  },\n});\n\nconst searchLatestReleaseNotes = createTool({\n  name: \"search_latest_release_notes\",\n  description: \"Search the latest release notes for relevant articles\",\n  parameters: z.object({\n    query: z.string().describe(\"The search query\"),\n  }),\n  handler: async ({ query }, { step }) => {\n    return await step?.run(\"search_latest_release_notes\", async () => {\n      \u002F\u002F Simulate knowledge base search\n      const results = releaseNotesDB.filter(\n        (releaseNote) =>\n          releaseNote.title.toLowerCase().includes(query.toLowerCase()) ||\n          releaseNote.content.toLowerCase().includes(query.toLowerCase())\n      );\n      return results;\n    });\n  },\n});\n\nconst getTicketDetails = async (ticketId: string) => {\n  const ticket = ticketsDB.find((t) => t.id === ticketId);\n  return ticket || { error: \"Ticket not found\" };\n};\n\n\u002F\u002F Create our agents\nconst customerSupportAgent = createAgent({\n  name: \"Customer Support\",\n  description:\n    \"I am a customer support agent that helps customers with their inquiries.\",\n  system: `You are a helpful customer support agent.\nYour goal is to assist customers with their questions and concerns.\nBe professional, courteous, and thorough in your responses.`,\n  model: anthropic({\n    model: \"claude-3-5-haiku-latest\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  tools: [\n    searchKnowledgeBase,\n    createTool({\n      name: \"update_ticket\",\n      description: \"Update a ticket with a note\",\n      parameters: z.object({\n        ticketId: z.string().describe(\"The ID of the ticket to update\"),\n        priority: z.string().describe(\"The priority of the ticket\"),\n        status: z.string().describe(\"The status of the ticket\"),\n        note: z.string().describe(\"A note to update the ticket with\"),\n      }),\n      handler: async ({ ticketId, priority, status, note }, { step }) => {\n        return await step?.run(\"update_ticket\", async () => {\n          \u002F\u002F TODO: Update the ticket in the database\n          return { message: \"Ticket updated successfully\" };\n        });\n      },\n    }),\n  ],\n});\n\nconst technicalSupportAgent = createAgent({\n  name: \"Technical Support\",\n  description: \"I am a technical support agent that helps critical tickets.\",\n  system: `You are a technical support specialist.\nYour goal is to help resolve critical tickets.\nUse your expertise to diagnose problems and suggest solutions.`,\n  model: anthropic({\n    model: \"claude-3-5-haiku-latest\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  tools: [searchLatestReleaseNotes],\n});\n\n\u002F\u002F Create our Routing Agent that will orchestrate the network of agents\n\u002F\u002F  and evaluate if the support request is answered.\nconst supervisorRoutingAgent = createRoutingAgent({\n  name: \"Supervisor\",\n  description: \"I am a Support supervisor.\",\n  system: `You are a supervisor.\nYour goal is to answer customer initial request or escalate the ticket if no answer can be provided.\nChoose to route tickets to the appropriate agent using the following instructions:\n- Critical tickets should be routed to the \"Technical Support\" agent.\n- Actions such as updating the ticket or handling non-critical tickets should be routed to the \"Customer Support\" agent.\n\nThink step by step and reason through your decision.\nWhen an agent as answered the ticket initial request or updated the ticket, call the \"done\" tool.`,\n  model: anthropic({\n    model: \"claude-3-5-haiku-latest\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  tools: [\n    createTool({\n      name: \"done\",\n      description: \"Call this when the ticket is solved or escalated\",\n      handler: async () => {},\n    }),\n    createTool({\n      name: \"route_to_agent\",\n      description: \"Route the ticket to the appropriate agent\",\n      parameters: z.object({\n        agent: z.string().describe(\"The agent to route the ticket to\"),\n      }),\n      handler: async ({ agent }) => {\n        return agent;\n      },\n    }),\n  ],\n  lifecycle: {\n    onRoute: ({ result, network }) => {\n      const lastMessage = lastResult(network?.state.results);\n\n      \u002F\u002F ensure to loop back to the last executing agent if a tool has been called\n      if (lastMessage && isLastMessageOfType(lastMessage, \"tool_call\")) {\n        return [lastMessage?.agent.name];\n      }\n\n      const tool = result.toolCalls[0];\n      if (!tool) {\n        return;\n      }\n      const toolName = tool.tool.name;\n      if (toolName === \"done\") {\n        return;\n      } else if (toolName === \"route_to_agent\") {\n        if (\n          typeof tool.content === \"object\" &&\n          tool.content !== null &&\n          \"data\" in tool.content &&\n          typeof tool.content.data === \"string\"\n        ) {\n          return [tool.content.data];\n        }\n      }\n      return;\n    },\n  },\n});\n\n\u002F\u002F Create a network with the agents with the routing agent\nconst supportNetwork = createNetwork({\n  name: \"Support Network\",\n  agents: [customerSupportAgent, technicalSupportAgent],\n  defaultModel: anthropic({\n    model: \"claude-3-5-haiku-latest\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  router: supervisorRoutingAgent,\n});\n```\n\nTry this agent network locally: [https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fsupport-agent-human-in-the-loop#readme](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fsupport-agent-human-in-the-loop#readme)\n\n> Both approaches are compatible with the `maxIter` parameters that enable you to put a maximum number of network iterations.\n> We recommend always setting a `master` value when using Agent-based routing.\n\n## Examples\n\n- [**The AgentKit SWE-bench example**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fswebench#readme) demonstrates how to build a network of agents solving a complex SWE bench challenge.\n- [**The Simple Search Agent**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fsimple-search-stagehand#readme) navigates the web autonomously to answer the given question\n- [**The Support Agent**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fsupport-agent-human-in-the-loop#readme) demonstrates how Inngest’s `waitForEvent()` enables the Agent to ask a human for help.\n- [**E2B Coding Agent**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fe2b-coding-agent#readme) replicates the Cursor’s Agent mode, creating a complete project from a simple prompt.\n- [**Daytona Coding Agent**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fdaytona-coding-agent#readme) creates web apps, runs tests, executes scripts, and more; accompanied with automated dev server detection and preview generation.\n\n## Contributing\n\nAfter cloning the repository:\n\n1. Ensure that you have `node` and `pnpm` installed\n\n```tsx\nnode -v # should be > 20.x\n\npnpm -v # should be > 9.x\n```\n\n2. Install dependencies:\n\n```tsx\npnpm i\n```\n\n3. Build the package or run tests:\n\n```tsx\npnpm build\n\npnpm test\n```\n\n**License**\n\n[Apache 2.0](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fblob\u002Fmain\u002FLICENSE.md)\n","# AgentKit\n\n*通过 MCP 构建具有确定性路由和丰富工具链的多智能体网络。*\n\n![AgentKit 跟踪](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Finngest_agent-kit_readme_26896112baba.png)\n\n\u003Cp align=\"center\">\n    \u003Ca href=\"https:\u002F\u002Fagentkit.inngest.com\u002Foverview\">文档\u003C\u002Fa>\n    \u003Cspan>&nbsp;·&nbsp;\u003C\u002Fspan>\n    \u003Ca href=\"https:\u002F\u002Fwww.inngest.com\u002Fblog?ref=github-agent-kit-readme\">博客\u003C\u002Fa>\n    \u003Cspan>&nbsp;·&nbsp;\u003C\u002Fspan>\n    \u003Ca href=\"https:\u002F\u002Fwww.inngest.com\u002Fdiscord\">社区\u003C\u002Fa>\n\u003C\u002Fp>\n\nAgentKit 提供更确定、更灵活的路由，兼容多家模型提供商，拥抱 MCP（以实现丰富的工具支持），并支持不断壮大、充满活力的 TypeScript AI 开发者社区。结合 Inngest 开发服务器，您可以在本地快速启动项目，并利用其编排引擎使您的智能体在部署到云端时具备容错能力。\n\n**核心概念**\n\n- [**智能体**](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Fagents)：可与提示词、[工具](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Ftools)以及 [MCP](https:\u002F\u002Fagentkit.inngest.com\u002Fadvanced-patterns\u002Fmcp) 结合使用的 LLM 调用。\n- [**网络**](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Fnetworks)：一种让智能体通过共享状态协作的简单方式，包括任务交接。\n- [**状态**](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Fstate)：将对话历史与完全类型化的状态机相结合，用于路由决策。\n- [**路由器**](https:\u002F\u002Fagentkit.inngest.com\u002Fconcepts\u002Frouters)：自主性的核心所在，从基于代码的编排到基于 LLM 的编排（例如 ReAct）。\n- [**追踪**](https:\u002F\u002Fagentkit.inngest.com\u002Fgetting-started\u002Flocal-development)：借助内置追踪功能，在本地和云端调试与优化工作流。\n\n立即开始吧！您可以 [克隆我们的示例](https:\u002F\u002Fagentkit.inngest.com\u002Fexamples\u002Foverview) 或 [浏览文档](https:\u002F\u002Fagentkit.inngest.com\u002Foverview)。\n\n## 快速入门\n\n```tsx\nnpm i @inngest\u002Fagent-kit inngest\n```\n\n**注意**：自 AgentKit v0.9.0 起，您需要将 `inngest` 作为独立依赖项与 `@inngest\u002Fagent-kit` 一同安装。这样做可以确保运行时兼容性，并避免多个包依赖不同版本的 Inngest 时产生冲突。\n\n## MCP 智能体示例\n\n在 Smithery 上选择您喜爱的 MCP 服务器（或自行托管一个），即可使用 MCP 作为工具构建 AgentKit 智能体。以下是一个使用 [Neon 数据库 MCP 服务器](https:\u002F\u002Fsmithery.ai\u002Fserver\u002Fneon) 的示例：\n\n```tsx\nimport {\n  anthropic,\n  createAgent,\n  createNetwork,\n  createTool,\n} from \"@inngest\u002Fagent-kit\";\nimport { createServer } from \"@inngest\u002Fagent-kit\u002Fserver\";\nimport { createSmitheryUrl } from \"@smithery\u002Fsdk\u002Fconfig.js\";\nimport { z } from \"zod\";\n\nconst neonServerUrl = createSmitheryUrl(\n  \"https:\u002F\u002Fserver.smithery.ai\u002Fneon\u002Fmcp?profile=bored-catshark-da8hf&api_key=123123123\"\n);\n\nconst neonAgent = createAgent({\n  name: \"neon-agent\",\n  system: `你是一位帮助管理 Neon 账户的助手。\n  重要提示：问题解答完毕后，请调用 'done' 工具。\n  `,\n  tools: [\n    createTool({\n      name: \"done\",\n      description: \"当任务完成后调用此工具。\",\n      parameters: z.object({\n        answer: z.string().describe(\"用户问题的答案。\"),\n      }),\n      handler: async ({ answer }, { network }) => {\n        network?.state.kv.set(\"answer\", answer);\n      },\n    }),\n  ],\n  mcpServers: [\n    {\n      name: \"neon\",\n      transport: {\n        type: \"streamable-http\",\n        url: neonServerUrl.toString(),\n      },\n    },\n  ],\n});\n\nconst neonAgentNetwork = createNetwork({\n  name: \"neon-agent\",\n  agents: [neonAgent],\n  defaultModel: anthropic({\n    model: \"claude-3-5-sonnet-20240620\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  router: ({ network }) => {\n    if (!network?.state.kv.get(\"answer\")) {\n      return neonAgent;\n    }\n    return;\n  },\n});\n\n\u002F\u002F 创建并启动服务器\nconst server = createServer({\n  networks: [neonAgentNetwork],\n});\n\nserver.listen(3010, () =>\n  console.log(\"Support Agent 示例服务器正在端口 3010 运行\")\n);\n```\n\n您可以通过以下链接在本地运行此示例：[https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fmcp-neon-agent#readme](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fmcp-neon-agent#readme)\n\n更多示例请参见下文。\n\n## 基于状态的确定性路由\n\nAgentKit 提供了一种独特的基于状态的确定性路由方法，能够在全程可控的前提下实现从基于代码的路由到完全自主路由的过渡。\n\n状态是同一网络中所有智能体之间存储和共享的关键值。\n\n该状态可被路由器、智能体生命周期回调、智能体提示词以及智能体工具访问：\n\n```mermaid\nflowchart LR\n\tsubgraph 网络\n\t\tstate[\"状态\"]\n\t\tsubgraph 智能体\n\t\t\tsystemp[\"系统提示词\"]\n\t\t\ttools[\"工具\"]\n\t\t\tlifecycle[\"生命周期回调\"]\n\t\tend\n\t\trouter[\"路由器\"]\n\tend\n\n\n\tstate-->systemp\n\tstate\u003C-->tools\n\tstate\u003C-->lifecycle\n\tstate\u003C-->router\n```\n\n*双向箭头表示读写访问权限，而单向箭头则表示只读访问权限。*\n\n这种共享状态与网络的消息历史相结合，构成了 AgentKit 确定性基于状态路由的基础。\n\n### 基于代码的路由\n\n我们建议从基于代码的路由开始，它能让你对网络的执行流程拥有完全的控制权。\n\n这种路由模式是最具确定性的。通过提供一个能够访问状态和历史记录的路由函数，你可以实现一种智能体式的路由机制，该机制会根据智能体工具所执行的状态更新做出响应。\n\n以下是一个编码智能体的例子，它使用基于代码的路由器，根据 `codeAssistantAgent` 生成的计划来编排网络中的各个智能体：\n\n```tsx\nimport { z } from \"zod\";\nimport {\n  anthropic,\n  createAgent,\n  createNetwork,\n  createTool,\n} from \"@inngest\u002Fagent-kit\";\n\nimport { readFileSync } from \"fs\";\nimport { join } from \"path\";\n\n\u002F\u002F 创建一个共享工具\nconst saveSuggestions = createTool({\n  name: \"save_suggestions\",\n  description: \"将其他智能体提出的建议保存到状态中\",\n  parameters: z.object({\n    suggestions: z.array(z.string()),\n  }),\n  handler: async (input, { network }) => {\n    const suggestions = network?.state.kv.get(\"suggestions\") || [];\n    network?.state.kv.set(\"suggestions\", [\n      ...suggestions,\n      ...input.suggestions,\n    ]);\n    return \"建议已保存！\";\n  },\n});\n\n\u002F\u002F 创建可使用 `saveSuggestions` 工具访问状态的智能体\nconst documentationAgent = createAgent({\n  name: \"documentation_agent\",\n  system: \"你是一位代码文档生成专家\",\n  tools: [saveSuggestions],\n});\n\nconst analysisAgent = createAgent({\n  name: \"analysis_agent\",\n  system: \"你是一位代码分析和改进建议专家\",\n  tools: [saveSuggestions],\n});\n\nconst summarizationAgent = createAgent({\n  name: \"summarization_agent\",\n  system: ({ network }) => {\n    const suggestions = network?.state.kv.get(\"suggestions\") || [];\n    return `请保存以下建议的摘要：\n    ${suggestions.join(\"\\n\")}`;\n  },\n  tools: [\n    createTool({\n      name: \"save_summary\",\n      description:\n        \"将其他智能体提出的建议摘要保存到状态中\",\n      parameters: z.object({\n        summary: z.string(),\n      }),\n      handler: async (input, { network }) => {\n        network?.state.kv.set(\"summary\", input.summary);\n        return \"已保存！\";\n      },\n    }),\n  ],\n});\n\n\u002F\u002F 创建生成计划的代码助手智能体\nconst codeAssistantAgent = createAgent({\n  name: \"code_assistant_agent\",\n  system: ({ network }) => {\n    const agents = Array.from(network?.agents.values() || [])\n      .filter(\n        (agent) =>\n          ![\"code_assistant_agent\", \"summarization_agent\"].includes(agent.name)\n      )\n      .map((agent) => `${agent.name} (${agent.system})`);\n    return `根据用户请求，仅执行以下工具调用：\n- 读取文件内容\n- 根据以下列表生成要运行的智能体计划：${agents.join(\", \")}\n\n完成后回答“完成”。`;\n  },\n  tools: [\n    createTool({\n      name: \"read_file\",\n      description: \"读取当前目录下的文件\",\n      parameters: z.object({\n        filename: z.string(),\n      }),\n      handler: async (input, { network }) => {\n        const filePath = join(process.cwd(), `files\u002F${input.filename}`);\n        const code = readFileSync(filePath, \"utf-8\");\n        network?.state.kv.set(\"code\", code);\n        return \"文件已读取！\";\n      },\n    }),\n    createTool({\n      name: \"generate_plan\",\n      description: \"生成要运行的智能体计划\",\n      parameters: z.object({\n        plan: z.array(z.string()),\n      }),\n      handler: async (input, { network }) => {\n        network?.state.kv.set(\"plan\", input.plan);\n        return \"计划已生成！\";\n      },\n    }),\n  ],\n});\n\nconst network = createNetwork({\n  name: \"code-assistant-v2\",\n  agents: [\n    codeAssistantAgent,\n    documentationAgent,\n    analysisAgent,\n    summarizationAgent,\n  ],\n  \u002F\u002F 我们的路由函数依赖共享状态来编排智能体\n  \u002F\u002F   首先调用 codeAssistantAgent，然后逐步执行其计划，\n  \u002F\u002F   直到摘要被写入状态。\n  router: ({ network }) => {\n    if (!network?.state.kv.has(\"code\") || !network?.state.kv.has(\"plan\")) {\n      return codeAssistantAgent;\n    } else {\n      const plan = (network?.state.kv.get(\"plan\") || []) as string[];\n      const nextAgent = plan.pop();\n      if (nextAgent) {\n        network?.state.kv.set(\"plan\", plan);\n        return network?.agents.get(nextAgent);\n      } else if (!network?.state.kv.has(\"summary\")) {\n        return summarizationAgent;\n      } else {\n        return undefined;\n      }\n    }\n  },\n  defaultModel: anthropic({\n    model: \"claude-3-5-sonnet-latest\",\n    defaultParameters: {\n      max_tokens: 4096,\n    },\n  }),\n});\n```\n\n源代码可在以下链接查看：[https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fblob\u002Fmain\u002Fexamples\u002Fcode-assistant-agentic\u002Fsrc\u002Findex.ts](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fblob\u002Fmain\u002Fexamples\u002Fcode-assistant-agentic\u002Fsrc\u002Findex.ts)\n\n### 基于代理的路由\n\n基于代理的路由用一个代理来替代传统的路由功能。这使得您的代理网络能够自主选择要执行的代理，并决定任务何时完成。\n\n路由代理配备了一个 `onRoute` 生命周期回调，它沿用了基于代码的路由方法。这个生命周期回调是您掌控代理路由决策的入口。\n\n下面的示例展示了一个支持代理，它使用路由代理作为“主管”：\n\n```tsx\nimport {\n  anthropic,\n  createAgent,\n  createNetwork,\n  createRoutingAgent,\n  createTool,\n} from \"@inngest\u002Fagent-kit\";\nimport { z } from \"zod\";\n\nimport { isLastMessageOfType, lastResult } from \".\u002Futils.js\";\n\nimport { knowledgeBaseDB, releaseNotesDB, ticketsDB } from \".\u002Fdatabases.js\";\n\n\u002F\u002F 创建共享工具\nconst searchKnowledgeBase = createTool({\n  name: \"search_knowledge_base\",\n  description: \"在知识库中搜索相关文章\",\n  parameters: z.object({\n    query: z.string().describe(\"搜索查询\"),\n  }),\n  handler: async ({ query }, { step }) => {\n    return await step?.run(\"search_knowledge_base\", async () => {\n      \u002F\u002F 模拟知识库搜索\n      const results = knowledgeBaseDB.filter(\n        (article) =>\n          article.title.toLowerCase().includes(query.toLowerCase()) ||\n          article.content.toLowerCase().includes(query.toLowerCase())\n      );\n      return results;\n    });\n  },\n});\n\nconst searchLatestReleaseNotes = createTool({\n  name: \"search_latest_release_notes\",\n  description: \"在最新发布说明中搜索相关文章\",\n  parameters: z.object({\n    query: z.string().describe(\"搜索查询\"),\n  }),\n  handler: async ({ query }, { step }) => {\n    return await step?.run(\"search_latest_release_notes\", async () => {\n      \u002F\u002F 模拟知识库搜索\n      const results = releaseNotesDB.filter(\n        (releaseNote) =>\n          releaseNote.title.toLowerCase().includes(query.toLowerCase()) ||\n          releaseNote.content.toLowerCase().includes(query.toLowerCase())\n      );\n      return results;\n    });\n  },\n});\n\nconst getTicketDetails = async (ticketId: string) => {\n  const ticket = ticketsDB.find((t) => t.id === ticketId);\n  return ticket || { error: \"工单未找到\" };\n};\n\n\u002F\u002F 创建我们的代理\nconst customerSupportAgent = createAgent({\n  name: \"客户支持\",\n  description:\n    \"我是一名客户支持代理，帮助客户解答疑问。\",\n  system: `你是一位乐于助人的客户支持代理。\n你的目标是协助客户解决他们的问题和疑虑。\n请以专业、礼貌和详尽的方式回复。`,\n  model: anthropic({\n    model: \"claude-3-5-haiku-latest\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  tools: [\n    searchKnowledgeBase,\n    createTool({\n      name: \"update_ticket\",\n      description: \"更新工单备注\",\n      parameters: z.object({\n        ticketId: z.string().describe(\"要更新的工单ID\"),\n        priority: z.string().describe(\"工单优先级\"),\n        status: z.string().describe(\"工单状态\"),\n        note: z.string().describe(\"要添加到工单的备注\"),\n      }),\n      handler: async ({ ticketId, priority, status, note }, { step }) => {\n        return await step?.run(\"update_ticket\", async () => {\n          \u002F\u002F TODO: 更新数据库中的工单\n          return { message: \"工单更新成功\" };\n        });\n      },\n    }),\n  ],\n});\n\nconst technicalSupportAgent = createAgent({\n  name: \"技术支持\",\n  description: \"我是一名技术支持代理，负责处理紧急工单。\",\n  system: `你是一位技术支持专家。\n你的目标是帮助解决紧急工单。\n运用你的专业知识诊断问题并提出解决方案。`,\n  model: anthropic({\n    model: \"claude-3-5-haiku-latest\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  tools: [searchLatestReleaseNotes],\n});\n\n\u002F\u002F 创建我们的路由代理，用于编排代理网络\n\u002F\u002F 并评估是否已回答支持请求。\nconst supervisorRoutingAgent = createRoutingAgent({\n  name: \"主管\",\n  description: \"我是一名支持主管。\",\n  system: `你是一位主管。\n你的目标是回答客户的初始请求，或者在无法提供答案时升级工单。\n请根据以下指示将工单路由到合适的代理：\n- 紧急工单应路由到“技术支持”代理。\n- 更新工单或处理非紧急工单等操作应路由到“客户支持”代理。\n\n请逐步思考并理性做出决策。\n当某个代理已经回答了工单的初始请求或更新了工单时，请调用“done”工具。`,\n  model: anthropic({\n    model: \"claude-3-5-haiku-latest\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  tools: [\n    createTool({\n      name: \"done\",\n      description: \"在工单解决或升级时调用此工具\",\n      handler: async () => {},\n    }),\n    createTool({\n      name: \"route_to_agent\",\n      description: \"将工单路由到合适的代理\",\n      parameters: z.object({\n        agent: z.string().describe(\"要路由到的代理名称\"),\n      }),\n      handler: async ({ agent }) => {\n        return agent;\n      },\n    }),\n  ],\n  lifecycle: {\n    onRoute: ({ result, network }) => {\n      const lastMessage = lastResult(network?.state.results);\n\n      \u002F\u002F 如果之前调用了工具，确保返回到上一个执行的代理\n      if (lastMessage && isLastMessageOfType(lastMessage, \"tool_call\")) {\n        return [lastMessage?.agent.name];\n      }\n\n      const tool = result.toolCalls[0];\n      if (!tool) {\n        return;\n      }\n      const toolName = tool.tool.name;\n      if (toolName === \"done\") {\n        return;\n      } else if (toolName === \"route_to_agent\") {\n        if (\n          typeof tool.content === \"object\" &&\n          tool.content !== null &&\n          \"data\" in tool.content &&\n          typeof tool.content.data === \"string\"\n        ) {\n          return [tool.content.data];\n        }\n      }\n      return;\n    },\n  },\n});\n\n\u002F\u002F 创建包含路由代理的支持网络\nconst supportNetwork = createNetwork({\n  name: \"支持网络\",\n  agents: [customerSupportAgent, technicalSupportAgent],\n  defaultModel: anthropic({\n    model: \"claude-3-5-haiku-latest\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  router: supervisorRoutingAgent,\n});\n```\n\n您可以在本地尝试这个代理网络：[https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fsupport-agent-human-in-the-loop#readme](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fsupport-agent-human-in-the-loop#readme)\n\n> 两种方法都兼容 `maxIter` 参数，该参数允许您设置网络迭代的最大次数。\n> 我们建议在使用基于代理的路由时，始终设置一个 `master` 值。\n\n## 示例\n\n- [**AgentKit SWE-bench 示例**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fswebench#readme) 展示了如何构建一个由多个智能体组成的网络，以解决复杂的 SWE bench 挑战。\n- [**简单搜索智能体**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fsimple-search-stagehand#readme) 能够自主地浏览网页，回答给定的问题。\n- [**支持智能体**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fsupport-agent-human-in-the-loop#readme) 展示了 Inngest 的 `waitForEvent()` 如何使智能体能够请求人类的帮助。\n- [**E2B 编码智能体**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fe2b-coding-agent#readme) 复现了 Cursor 的 Agent 模式，仅凭一个简单的提示就能创建出完整的项目。\n- [**Daytona 编码智能体**](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Ftree\u002Fmain\u002Fexamples\u002Fdaytona-coding-agent#readme) 可以创建 Web 应用、运行测试、执行脚本等，并且还具备自动检测开发服务器和生成预览的功能。\n\n## 贡献\n\n克隆仓库后：\n\n1. 确保已安装 `node` 和 `pnpm`：\n\n```tsx\nnode -v # 应该是 > 20.x\n\npnpm -v # 应该是 > 9.x\n```\n\n2. 安装依赖：\n\n```tsx\npnpm i\n```\n\n3. 构建包或运行测试：\n\n```tsx\npnpm build\n\npnpm test\n```\n\n**许可证**\n\n[Apache 2.0](https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fblob\u002Fmain\u002FLICENSE.md)","# AgentKit 快速上手指南\n\nAgentKit 是一个用于构建多智能体（Multi-Agent）网络的开源框架。它支持确定性路由、丰富的工具集成（通过 MCP 协议），并结合 Inngest 引擎确保工作流在云端部署时的容错性。\n\n## 环境准备\n\n在开始之前，请确保您的开发环境满足以下要求：\n\n*   **Node.js**: 建议安装 LTS 版本（v18 或更高）。\n*   **包管理器**: npm, yarn, pnpm 或 bun。\n*   **API Keys**: 准备好您使用的 LLM 提供商（如 Anthropic, OpenAI 等）的 API 密钥。\n*   **MCP Server (可选)**: 如果需要使用模型上下文协议（MCP）工具，需配置相应的 MCP 服务器地址。\n\n> **注意**：从 AgentKit v0.9.0 开始，`inngest` 必须作为独立的依赖项安装，以确保运行时兼容性。\n\n## 安装步骤\n\n使用 npm 安装核心库和运行时引擎：\n\n```bash\nnpm i @inngest\u002Fagent-kit inngest\n```\n\n如果您使用其他包管理器，命令如下：\n*   **yarn**: `yarn add @inngest\u002Fagent-kit inngest`\n*   **pnpm**: `pnpm add @inngest\u002Fagent-kit inngest`\n\n## 基本使用\n\n以下是一个最简化的示例，展示如何创建一个基于 MCP 工具的单个智能体，并将其放入网络中运行。本例使用了 Neon 数据库的 MCP 服务作为工具来源。\n\n### 1. 创建入口文件\n\n新建一个文件（例如 `index.ts`），并填入以下代码：\n\n```tsx\nimport {\n  anthropic,\n  createAgent,\n  createNetwork,\n  createTool,\n} from \"@inngest\u002Fagent-kit\";\nimport { createServer } from \"@inngest\u002Fagent-kit\u002Fserver\";\nimport { createSmitheryUrl } from \"@smithery\u002Fsdk\u002Fconfig.js\";\nimport { z } from \"zod\";\n\n\u002F\u002F 配置 MCP 服务器地址 (此处以 Neon 为例)\nconst neonServerUrl = createSmitheryUrl(\n  \"https:\u002F\u002Fserver.smithery.ai\u002Fneon\u002Fmcp?profile=bored-catshark-da8hf&api_key=YOUR_API_KEY\"\n);\n\n\u002F\u002F 定义智能体\nconst neonAgent = createAgent({\n  name: \"neon-agent\",\n  system: `You are a helpful assistant that help manage a Neon account.\n  IMPORTANT: Call the 'done' tool when the question is answered.\n  `,\n  tools: [\n    createTool({\n      name: \"done\",\n      description: \"Call this tool when you are finished with the task.\",\n      parameters: z.object({\n        answer: z.string().describe(\"Answer to the user's question.\"),\n      }),\n      handler: async ({ answer }, { network }) => {\n        \u002F\u002F 将结果存入共享状态\n        network?.state.kv.set(\"answer\", answer);\n      },\n    }),\n  ],\n  \u002F\u002F 挂载 MCP 服务器作为工具集\n  mcpServers: [\n    {\n      name: \"neon\",\n      transport: {\n        type: \"streamable-http\",\n        url: neonServerUrl.toString(),\n      },\n    },\n  ],\n});\n\n\u002F\u002F 创建智能体网络\nconst neonAgentNetwork = createNetwork({\n  name: \"neon-agent-network\",\n  agents: [neonAgent],\n  defaultModel: anthropic({\n    model: \"claude-3-5-sonnet-20240620\",\n    defaultParameters: {\n      max_tokens: 1000,\n    },\n  }),\n  \u002F\u002F 简单的确定性路由：如果没有答案，则调用 neonAgent\n  router: ({ network }) => {\n    if (!network?.state.kv.get(\"answer\")) {\n      return neonAgent;\n    }\n    return; \u002F\u002F 任务完成，结束路由\n  },\n});\n\n\u002F\u002F 启动本地服务器\nconst server = createServer({\n  networks: [neonAgentNetwork],\n});\n\nserver.listen(3010, () =>\n  console.log(\"AgentKit server is running on port 3010\")\n);\n```\n\n### 2. 配置环境变量\n\n确保在终端或 `.env` 文件中设置必要的 API 密钥（根据您的模型提供商和 MCP 服务调整）：\n\n```bash\nexport ANTHROPIC_API_KEY=\"your_anthropic_key\"\n# 如果使用 Smithery 或其他 MCP 服务，可能还需要配置相关 Key\n```\n\n### 3. 运行项目\n\n使用 TypeScript 运行环境（如 `tsx` 或 `ts-node`）启动服务：\n\n```bash\nnpx tsx index.ts\n```\n\n启动成功后，控制台将显示：\n`AgentKit server is running on port 3010`\n\n此时，您可以结合 **Inngest Dev Server** 在本地调试工作流，或通过 HTTP 请求触发智能体网络。\n\n### 核心概念简述\n\n*   **Agents**: 封装了 LLM 调用、提示词和工具（包括 MCP 工具）的基本单元。\n*   **Networks**: 让多个智能体协作的容器，它们共享一个类型安全的 **State**（状态）。\n*   **Routers**: 决定下一个执行哪个智能体的逻辑。可以是纯代码控制（确定性最高），也可以由另一个 LLM 智能体自主决定。\n*   **State**: 键值对存储，用于在智能体之间传递数据和记忆，是实现复杂工作流编排的关键。\n\n更多高级用法（如多智能体协作、代码级路由编排）请参考官方文档或 GitHub 仓库中的 `examples` 目录。","某 SaaS 初创团队需要构建一个能自动查询 Neon 数据库并回答用户账单问题的智能客服系统。\n\n### 没有 agent-kit 时\n- **路由逻辑脆弱**：开发者需手动编写复杂的 `if-else` 代码来判断何时调用数据库、何时直接回复，一旦流程变动极易出错且难以维护。\n- **工具集成繁琐**：接入外部 MCP 服务（如数据库接口）需要重复造轮子编写底层通信协议，缺乏统一标准，调试困难。\n- **状态管理混乱**：多轮对话中的上下文和中间数据（如查询结果）依赖全局变量或临时存储，类型不安全，容易导致数据丢失或错乱。\n- **故障恢复缺失**：若云端部署时遇到网络波动或 API 超时，任务直接失败，缺乏内置的重试机制和持久化队列保障。\n- **可观测性差**：无法直观追踪 Agent 的决策路径和工具调用细节，排查问题如同“黑盒”操作，效率极低。\n\n### 使用 agent-kit 后\n- **确定性路由编排**：利用 Typed State Machine 定义清晰的状态流转，代码即逻辑，确保 Agent 在“查询”与“回答”间精准切换，无需手写复杂判断。\n- **原生 MCP 支持**：通过简单配置即可接入 Smithery 上的 Neon 数据库 MCP 服务，像调用本地函数一样使用远程工具，开发效率倍增。\n- **类型安全的状态共享**：Network 层面的共享状态自动结合对话历史，全程 TypeScript 类型提示，彻底杜绝运行时数据错误。\n- **云原生容错能力**：结合 Inngest 引擎，自动处理重试、延迟执行和断点续传，即使部署在云端也能保证任务最终成功交付。\n- **全链路可视化追踪**：内置 Tracing 功能让开发者在本地或云端实时查看每一步推理和工具调用，快速定位并优化瓶颈。\n\nagent-kit 将原本碎片化、易出错的代理开发流程，转变为类型安全、可观测且具备工业级可靠性的标准化网络构建体验。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Finngest_agent-kit_c251e36a.png","inngest","Inngest","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002Finngest_03c2e4c2.png","Inngest is the developer platform for easily building reliable workflows with zero infrastructure",null,"hello@inngest.com","https:\u002F\u002Fwww.inngest.com\u002F","https:\u002F\u002Fgithub.com\u002Finngest",[84,88],{"name":85,"color":86,"percentage":87},"TypeScript","#3178c6",99.8,{"name":89,"color":90,"percentage":91},"JavaScript","#f1e05a",0.2,824,121,"2026-04-03T07:34:51","Apache-2.0","未说明",{"notes":98,"python":99,"dependencies":100},"该工具是基于 TypeScript 的 AI 代理开发框架，运行在 Node.js 环境中而非 Python。从 v0.9.0 开始，需要将 'inngest' 作为独立依赖安装。支持通过 MCP (Model Context Protocol) 集成外部工具，并可与 Inngest Dev Server 配合进行本地开发和云端部署。","不适用 (基于 Node.js\u002FTypeScript)",[101,75,102,103],"@inngest\u002Fagent-kit","@smithery\u002Fsdk","zod",[15,14,26,13],[106,107,108,109,110],"agent","ai","ai-agent-framework","ai-agents","llm","2026-03-27T02:49:30.150509","2026-04-06T06:45:55.535867",[114,119,124,129,134,139],{"id":115,"question_zh":116,"answer_zh":117,"source_url":118},14120,"遇到 'ERR_REQUIRE_ESM' 错误，提示在 CommonJS 模块中无法 require ES 模块怎么办？","这是由于 AgentKit（CommonJS）依赖了纯 ES 模块（如 @dmitryrechkin\u002Fjson-schema-to-zod）导致的兼容性问题。目前官方正在努力支持 CommonJS，但由于 AI 生态系统中许多新库仅支持 ESM，完全解决较困难。\n临时解决方案：\n1. 尝试在项目根目录的 package.json 中添加 \"type\": \"module\" 将整个项目转为 ESM（但这可能引发其他依赖问题）。\n2. 使用包管理器的覆盖功能（如 pnpm.overrides）强制指定依赖版本或方向。\n3. 等待官方后续对 CJS 支持的进一步优化或文档说明。","https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fissues\u002F81",{"id":120,"question_zh":121,"answer_zh":122,"source_url":123},14121,"运行 deep-research 示例时报错 'Cannot read properties of undefined (reading 'step')' 如何解决？","该错误通常是由于使用了不稳定的正式版本导致的。请安装指定的 canary（预览）版本来修复此问题。\n执行以下命令安装修复后的版本：\nnpm install @inngest\u002Fagent-kit@0.13.2-alpha-20251107125129-caccd8a0430bd554cc98f8eea109c9677267b276\n安装后重新运行示例即可正常工作。","https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fissues\u002F244",{"id":125,"question_zh":126,"answer_zh":127,"source_url":128},14122,"如何在 AgentKit 中向 LLM 请求传递超参数（如 temperature, top_p 等）？","从 @inngest\u002Fagent-kit v0.4.0 版本开始，已支持配置模型超参数。\n您可以在模型配置中直接设置 temperature 等参数。\n详细用法请参考官方文档：https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fblob\u002Fmain\u002Fdocs\u002Fconcepts\u002Fmodels.mdx#configure-model-hyper-parameters-temperature-etc","https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fissues\u002F69",{"id":130,"question_zh":131,"answer_zh":132,"source_url":133},14123,"使用 network 时出现 'AUTOMATIC_PARALLEL_INDEXING' 警告或无限函数循环怎么办？","当通过 HTTP（如使用 createServer() 配合 Inngest DevServer）服务 AgentKit network 时，出现此警告是预期行为。AgentKit 基于 Inngest 构建，确保每次迭代都是幂等的。\n解决方案：\n1. 如果您使用的是 AgentKit 导出的 createServer，该问题在 v0.7.1 及以上版本已修复，请升级版本。\n2. 如果您直接使用 inngest 客户端，请在初始化时添加 optimizeParallelism: true 选项。\n3. 建议为并行步骤使用唯一的 ID，避免重复。","https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fissues\u002F126",{"id":135,"question_zh":136,"answer_zh":137,"source_url":138},14124,"升级 inngest 到 v3.42.1 后，agent-kit v0.9.0 出现模块导出错误（Module export errors）如何解决？","这是因为 agent-kit v0.9.0 尝试导入 inngest v3.42.1 中不再导出的内部模块（如 .\u002Fcomponents\u002FInngestFunction）。\n解决方法是升级 @inngest\u002Fagent-kit 到与新版 inngest 兼容的版本。请检查并更新您的 package.json，确保使用最新版的 agent-kit，通常新版本会适配最新的 inngest 主包接口。如果问题依旧，请暂时回退 inngest 版本至兼容版本或关注官方发布的兼容性补丁。","https:\u002F\u002Fgithub.com\u002Finngest\u002Fagent-kit\u002Fissues\u002F218",{"id":140,"question_zh":141,"answer_zh":142,"source_url":133},14125,"如何在 Network 中避免重复创建 MCP 客户端或会话？","默认情况下，Network 中的每次 agent-run 都会创建新的 MCP 客户端\u002F会话，这可能导致资源浪费。\n优化方案：\n1. 在 createAgent 外部调用 agent.listMCPTools(mcpServer) 获取工具列表。\n2. 将生成的 MCP 工具注入到 agent.tools 中，而不是让每个 agent 实例独立创建。\n这样可以复用工具实例，减少不必要的 MCP 会话创建。",[144,149,154,159,164,169,174,179,184,189,194,199,204,209,214,219,224,229,234,239],{"id":145,"version":146,"summary_zh":147,"released_at":148},80845,"@inngest\u002Fagent-kit@0.13.2","### 补丁变更\n\n-   3818d37：在 `inngest@3.45.0` 更新后，支持多种 `AsyncContext` 形状\n","2025-11-13T15:27:01",{"id":150,"version":151,"summary_zh":152,"released_at":153},80846,"@inngest\u002Fagent-kit@0.13.1","### 补丁变更\n\n-   07ae4dd：从打包的 CommonJS 模块中移除未使用的 `json-schema-to-zod` 依赖\n","2025-10-07T19:30:40",{"id":155,"version":156,"summary_zh":157,"released_at":158},80847,"@inngest\u002Fuse-agent@0.4.0","### 小幅改动\n\n-   2ffb890：将历史记录强类型化，使用 AgentKitMessage\n","2025-10-01T21:08:57",{"id":160,"version":161,"summary_zh":162,"released_at":163},80848,"@inngest\u002Fagent-kit@0.13.0","### 小幅变更\n\n-   c9b0b16：支持 inngest 最新版本（3.43.1）\n    集成了 @inngest\u002Fai 提供的 Azure OpenAI 模型\n    迁移到 zod v4，并移除了 zod-to-json-schema 包，改用 zod 原生的 z.toJSONSchema() 方法","2025-09-27T00:27:07",{"id":165,"version":166,"summary_zh":167,"released_at":168},80849,"@inngest\u002Fagent-kit@0.12.1","### 补丁变更\n\n-   4a81376：将 `json-schema-to-zod` 的静态导入替换为在使用该库的函数内部进行动态 `import()`，以解决在使用 `require()` 的 CommonJS 项目中加载 agentkit 时出现的崩溃问题。\n","2025-09-25T17:14:12",{"id":170,"version":171,"summary_zh":172,"released_at":173},80850,"@inngest\u002Fuse-agent@0.3.0","### 小幅更新\n\n-   b175718：# 新包：@inngest\u002Fuse-agent\n\n    推出一套全面的 React 钩子库，用于构建基于 AgentKit 网络的 AI 聊天界面。\n\n    ## 新内容\n\n    **@inngest\u002Fuse-agent** 是一个独立的 npm 包，提供了一整套用于与 AgentKit 集成的 React 钩子。该包提取并整合了构建复杂 AI 聊天应用所需的所有 React 功能。\n\n    ### 核心特性\n\n    -   **核心钩子**：`useAgent`、`useChat`、`useThreads`，用于实时流式传输和线程管理\n    -   **实用钩子**：`useEphemeralThreads`、`useConversationBranching`、`useEditMessage`、`useMessageActions`、`useSidebar`、`useIsMobile`\n    -   **提供者系统**：`AgentProvider` 用于共享连接和配置\n    -   **传输层**：可配置的 API 层，包含 `DefaultAgentTransport` 和自定义传输支持\n    -   **TypeScript 支持**：所有钩子和组件均提供完整的类型定义\n    -   **Next.js 兼容性**：所有钩子均已正确标记为 `\"use client\"` 指令\n\n    ### 安装\n\n    ```bash\n    npm install @inngest\u002Fuse-agents\n    # 对等依赖\n    npm install react @inngest\u002Frealtime uuid\n    ```\n\n    ### 基本用法\n\n    ```typescript\n    import { useChat, AgentProvider } from '@inngest\u002Fuse-agents';\n\n    function App() {\n      return (\n        \u003CAgentProvider userId=\"user-123\">\n          \u003CChatComponent \u002F>\n        \u003C\u002FAgentProvider>\n      );\n    }\n\n    function ChatComponent() {\n      const { messages, sendMessage, status } = useChat();\n      return \u003Cdiv>\u002F* 您的聊天 UI *\u002F\u003C\u002Fdiv>;\n    }\n    ```\n\n    ### 为何选择此包\n\n    该包使开发者能够：\n\n    -   构建 AI 聊天应用而无需从头开始开发\n    -   利用预先构建且经过实战检验的 React 钩子进行 AgentKit 集成\n    -   在不同项目中保持一致的开发模式\n    -   将精力集中在 UI\u002FUX 上，而非底层的流式传输和状态管理\n\n    ### 迁移指南\n\n    如果您之前使用的是来自 AgentKit 示例的本地钩子，请替换本地导入：\n\n    ```typescript\n    \u002F\u002F 之前\n    import { useChat } from \"@\u002Fhooks\";\n    import { AgentProvider } from \"@\u002Fcontexts\u002FAgentContext\";\n\n    \u002F\u002F 之后\n    import { useChat, AgentProvider } from \"@inngest\u002Fuse-agents\";\n    ```\n\n    不需要进行任何功能上的更改——API 与之前的本地实现完全相同。","2025-09-24T20:49:38",{"id":175,"version":176,"summary_zh":177,"released_at":178},80851,"@inngest\u002Fagent-kit@0.12.0","### 小幅变更\n\n-   b175718：# 全面的 AgentKit 增强\n\n    对 AgentKit 进行了重大改进，包括增强的文档、新的 API 路由、全面的 UI 组件以及示例应用。\n\n    ## 📚 文档增强\n\n    **新增高级模式指南：**\n\n    -   添加了 `legacy-ui-streaming.mdx`——使用 useAgent 钩子进行 UI 流式传输的指南\n    -   添加了 `use-chat.mdx`——构建聊天界面的综合指南\n    -   添加了 `use-threads.mdx`——管理对话线程的文档\n    -   添加了 `use-agent.mdx`——更新的代理集成模式\n\n    **文档重组：**\n\n    -   将 UI 流式传输相关指南移至专门的 UI 集成章节\n    -   通过实际示例增强了高级模式部分\n    -   新增序列图和使用指南\n\n    ## ⚡ 革命性的自动事件流系统\n\n    **全面的流式架构：**\n\n    -   **StreamingContext**：用于网络\u002F代理运行的层次化上下文管理，共享序列计数器\n    -   **事件模式**：15 种以上的事件类型，覆盖完整的代理生命周期（run.started、part.created、text.delta、工具调用、HITL 等）\n    -   **自动丰富**：事件会自动添加 threadId、userId 和上下文元数据\n    -   **序列管理**：单调递增的序列号，确保跨上下文的事件完美有序\n    -   **父\u002F子上下文**：在网络运行中，代理运行可无缝继承上下文\n    -   **基于代理的步骤包装器**：与 Inngest 步骤透明集成，且不会破坏现有代码\n    -   **最佳努力发布**：优雅的错误处理机制，绝不会中断代理执行\n    -   **OpenAI 兼容 ID**：在 OpenAI 的 40 字符限制内自动生成工具调用 ID\n\n    **支持的事件类型：**\n\n    -   **生命周期事件**：`run.started`、`run.completed`、`run.failed`、`run.interrupted`\n    -   **内容流式传输**：`text.delta`、`reasoning.delta`、`data.delta`\n    -   **工具集成**：`tool_call.arguments.delta`、`tool_call.output.delta`\n    -   **部分管理**：`part.created`、`part.completed`、`part.failed`\n    -   **HITL 支持**：`hitl.requested`、`hitl.resolved`\n    -   **元数据与控制**：`usage.updated`、`metadata.updated`、`stream.ended`\n\n    **开发者体验：**\n\n    -   **零配置**：自动从网络状态中提取上下文\n    -   **调试日志记录**：提供全面的调试输出，便于开发\n    -   **共享序列计数器**：确保多个上下文中的事件完美有序\n    -   **灵活发布**：可配置的发布函数，适用于任何传输方式\n\n    该流式系统能够实现与 `useAgent` 钩子预期完全一致的实时 UI 更新，从而建立无缝的代理与 UI 通信。\n\n    ## 🚀 新的 API 路径与后端功能\n\n    **聊天与通信：**\n\n    -   `POST \u002Fapi\u002Fchat`——主聊天端点，带有 Zod 验证和 Inngest 集成\n    -   `POST \u002Fapi\u002Fchat\u002Fcance","2025-09-24T20:49:35",{"id":180,"version":181,"summary_zh":182,"released_at":183},80852,"@inngest\u002Fagent-kit@0.11.0","### 小幅变更\n\n-   81c90df：# AgentKit 全面增强\n\n    对 AgentKit 进行了重大改进，包括增强的文档、新增的 API 路由、全面的 UI 组件以及示例应用。\n\n    ## 📚 文档增强\n\n    **新增高级模式指南：**\n\n    -   添加 `legacy-ui-streaming.mdx` - 使用 useAgent 钩子进行 UI 流式传输的指南\n    -   添加 `use-chat.mdx` - 构建聊天界面的综合指南\n    -   添加 `use-threads.mdx` - 管理对话线程的文档\n    -   添加 `use-agent.mdx` - 更新的代理集成模式\n\n    **文档重组：**\n\n    -   将 UI 流式传输指南移至专门的 UI 集成章节\n    -   通过实际示例增强了高级模式\n    -   新增序列图和使用指南\n\n    ## ⚡ 革命性的自动事件流系统\n\n    **全面的流式架构：**\n\n    -   **StreamingContext**：用于网络\u002F代理运行的层次化上下文管理，共享序列计数器\n    -   **事件模式**：15 种以上的事件类型，覆盖完整的代理生命周期（run.started、part.created、text.delta、工具调用、HITL 等）\n    -   **自动丰富**：事件会自动添加 threadId、userId 和上下文元数据\n    -   **序列管理**：单调递增的序列号，确保跨上下文的完美事件顺序\n    -   **父\u002F子上下文**：在网络运行中，代理运行可无缝继承上下文\n    -   **基于代理的步骤包装器**：与 Inngest 步骤透明集成，无需修改现有代码\n    -   **尽力而为的发布机制**：优雅的错误处理，绝不会中断代理执行\n    -   **OpenAI 兼容 ID**：在 OpenAI 的 40 字符限制内自动生成工具调用 ID\n\n    **支持的事件类型：**\n\n    -   **生命周期事件**：`run.started`、`run.completed`、`run.failed`、`run.interrupted`\n    -   **内容流式传输**：`text.delta`、`reasoning.delta`、`data.delta`\n    -   **工具集成**：`tool_call.arguments.delta`、`tool_call.output.delta`\n    -   **部分管理**：`part.created`、`part.completed`、`part.failed`\n    -   **HITL 支持**：`hitl.requested`、`hitl.resolved`\n    -   **元数据与控制**：`usage.updated`、`metadata.updated`、`stream.ended`\n\n    **开发者体验：**\n\n    -   **零配置**：从网络状态中自动提取上下文\n    -   **调试日志记录**：提供全面的调试输出，便于开发\n    -   **共享序列计数器**：确保跨多个上下文的完美事件顺序\n    -   **灵活的发布机制**：可配置的发布函数，适用于任何传输方式\n\n    该流式系统能够实现与 `useAgent` 钩子期望完全匹配的实时 UI 更新，从而建立无缝的代理与 UI 通信。\n\n    ## 🚀 新增 API 路由及后端功能\n\n    **聊天与通信：**\n\n    -   `POST \u002Fapi\u002Fchat` - 主聊天端点，配备 Zod 验证和 Inngest 集成\n    -   `POST \u002Fapi\u002Fchat\u002Fcance","2025-09-24T14:56:37",{"id":185,"version":186,"summary_zh":187,"released_at":188},80853,"@inngest\u002Fuse-agent@0.2.0","### 小幅更新\n\n-   81c90df：# 新包：@inngest\u002Fuse-agent\n\n    推出一个全面的 React 钩子库，用于构建基于 AgentKit 网络的 AI 聊天界面。\n\n    ## 新内容\n\n    **@inngest\u002Fuse-agent** 是一个独立的 npm 包，提供了一整套用于与 AgentKit 集成的 React 钩子。该包提取并整合了构建复杂 AI 聊天应用所需的所有 React 功能。\n\n    ### 核心特性\n\n    -   **核心钩子**：`useAgent`、`useChat`、`useThreads`，用于实时流式传输和线程管理\n    -   **工具钩子**：`useEphemeralThreads`、`useConversationBranching`、`useEditMessage`、`useMessageActions`、`useSidebar`、`useIsMobile`\n    -   **提供者系统**：`AgentProvider` 用于共享连接和配置\n    -   **传输层**：可配置的 API 层，包含 `DefaultAgentTransport` 和自定义传输支持\n    -   **TypeScript 支持**：所有钩子和组件的完整类型定义\n    -   **Next.js 兼容性**：所有钩子都正确标记了 `\"use client\"` 指令\n\n    ### 安装\n\n    ```bash\n    npm install @inngest\u002Fuse-agents\n    # 对等依赖\n    npm install react @inngest\u002Frealtime uuid\n    ```\n\n    ### 基本用法\n\n    ```typescript\n    import { useChat, AgentProvider } from '@inngest\u002Fuse-agents';\n\n    function App() {\n      return (\n        \u003CAgentProvider userId=\"user-123\">\n          \u003CChatComponent \u002F>\n        \u003C\u002FAgentProvider>\n      );\n    }\n\n    function ChatComponent() {\n      const { messages, sendMessage, status } = useChat();\n      return \u003Cdiv>\u002F* 您的聊天 UI *\u002F\u003C\u002Fdiv>;\n    }\n    ```\n\n    ### 为何选择此包\n\n    该包使开发者能够：\n\n    -   构建 AI 聊天应用而无需从头开始开发\n    -   利用预先构建且经过实战检验的 React 钩子进行 AgentKit 集成\n    -   在不同项目中保持一致的模式\n    -   专注于 UI\u002FUX，而非底层的流式传输和状态管理\n\n    ### 迁移指南\n\n    如果您之前使用的是来自 AgentKit 示例的本地钩子，请替换本地导入：\n\n    ```typescript\n    \u002F\u002F 之前\n    import { useChat } from \"@\u002Fhooks\";\n    import { AgentProvider } from \"@\u002Fcontexts\u002FAgentContext\";\n\n    \u002F\u002F 之后\n    import { useChat, AgentProvider } from \"@inngest\u002Fuse-agents\";\n    ```\n\n    无需进行任何功能上的更改——API 与之前的本地实现完全相同。\n","2025-09-24T14:56:34",{"id":190,"version":191,"summary_zh":192,"released_at":193},80854,"@inngest\u002Fagent-kit@0.9.0","### 小幅改动\n\n-   d9507fb：通过 HistoryAdapters 添加了对持久化对话历史的支持\n    创建了一个具有实时响应和线程管理功能的 Next.js 示例应用\n","2025-07-01T19:24:38",{"id":195,"version":196,"summary_zh":197,"released_at":198},80855,"@inngest\u002Fagent-kit@0.8.4","### Patch Changes\n\n-   fed9545: fixed deserialization of state losing messages and results in Inngest context\n","2025-07-01T18:38:43",{"id":200,"version":201,"summary_zh":202,"released_at":203},80856,"@inngest\u002Fagent-kit@0.8.3","### Patch Changes\n\n-   2f56454: fixed issue with openai parser not handling responses with both text and tool call parts\n","2025-06-20T01:51:44",{"id":205,"version":206,"summary_zh":207,"released_at":208},80857,"@inngest\u002Fagent-kit@0.8.2","### Patch Changes\n\n-   f09cb8e: Adding recursive check for removing additionalProperties for gemini.\n","2025-06-19T16:24:48",{"id":210,"version":211,"summary_zh":212,"released_at":213},80858,"@inngest\u002Fagent-kit@0.8.1","### Patch Changes\n\n-   f476961: Fixed Gemini adapter response parsing & malformed function call handling\n","2025-06-18T21:22:34",{"id":215,"version":216,"summary_zh":217,"released_at":218},80859,"@inngest\u002Fagent-kit@0.8.0","### Minor Changes\n\n-   e59c6fd: Added support for StreamableHttp in MCP Client\n\n### Patch Changes\n\n-   43a0745: Removed redundant call to this.listMCPTools(server) as we are now using a promises array to handle multiple servers concurrently\n\n    Fixed conditional in MCP client initialization and moved this.\\_mcpClients.push(client) to the beginning of listMCPTools method to prevent duplicate clients from being registered\n","2025-05-14T19:12:44",{"id":220,"version":221,"summary_zh":222,"released_at":223},80860,"@inngest\u002Fagent-kit@0.7.3","### Patch Changes\n\n-   5e3e74f: Export types\n-   5e3e74f: Export types from `index.ts`\n","2025-04-16T08:00:33",{"id":225,"version":226,"summary_zh":227,"released_at":228},80861,"@inngest\u002Fagent-kit@0.7.2","### Patch Changes\n\n-   b983424: Add safety checks to openai response parser\n-   bf01b2f: fix(gemini): do not send `tools` and `tool_config` if not tools are provided\n","2025-04-09T08:35:54",{"id":230,"version":231,"summary_zh":232,"released_at":233},80862,"@inngest\u002Fagent-kit@0.7.1","### Patch Changes\n\n-   f630722: Optimize parallelism in `createServer()`, removing risk of parallel indexing\n","2025-04-07T10:08:42",{"id":235,"version":236,"summary_zh":237,"released_at":238},80863,"@inngest\u002Fagent-kit@0.7.0","### Minor Changes\n\n-   a5f2fea: Refactor AgentResult, and allow conversational history + short term mem\n","2025-03-21T22:20:52",{"id":240,"version":241,"summary_zh":242,"released_at":243},80864,"@inngest\u002Fagent-kit@0.6.0","### Minor Changes\n\n-   e32af3d: Implement typed state management\n\n### Patch Changes\n\n-   51a076c: Document typed state, re-add KV for backcompat\n-   7eeadbd: fix(network): add back-compat for `defaultRouter`\n","2025-03-20T17:29:02"]