# agentscope-java-e2e-pipeline **Repository Path**: alimei/agentscope-java-e2e-pipeline ## Basic Information - **Project Name**: agentscope-java-e2e-pipeline - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-07 - **Last Updated**: 2026-08-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AgentScope Java 2.0 端到端 Pipeline:微信公众号排版 Agent 用 **AgentScope Java 2.0.0** 跑通一条端到端流水线,把 **ReActAgent + HarnessAgent + Skill + MCP + SubAgent + 自研 Function Call(@Tool)** 五大能力串在一个 pipeline 里,接 **DeepSeek**,场景是**微信公众号排版**。 ## 流水线 ``` 选题 → ② MCP 调 exomind 的 query/search 取素材 → ③ SubAgent 委派 content-writer 把素材整合成 Markdown 正文(独立上下文) → ③.5 @Tool estimate_readtime 算字数 / 阅读时长 → ④ Skill wechat-format(doocs/md 排版知识,按需加载) + @Tool render_wechat_html 确定性渲染成微信内联样式 HTML → ④.5 @Tool validate_wechat_html 微信兼容性质量门 → ⑤ write_file 落本地 article.html(doocs/md 内联样式,可手动粘公众号) → ⑥ @Tool publish_to_wechat 投公众号草稿箱(设 PUBLISH_ACCOUNT 才启用,否则跳过) ``` 底层全靠 ReAct 的 **function call**:MCP / Skill / SubAgent 都通过 `tool_call` 触发(间接),`PublisherToolkit` 里 4 个 `@Tool` 是我们亲手写的(直接)。 ## 能力对照 | 能力 | 在 pipeline 里的落点 | 关键文件 | |---|---|---| | **ReActAgent + HarnessAgent** | 一个 `HarnessAgent` 实例 = ReAct 内核 + Harness 外壳 | `WeChatPublisher.java` | | **DeepSeek 接入** | `OpenAIChatModel` 指向 deepseek base_url | `WeChatPublisher.java` | | **Skill** | `wechat-format`(doocs/md 排版知识,workspace 自动加载) | `workspace/skills/wechat-format/SKILL.md` | | **MCP** | exomind `mcp` stdio 服务(workspace `tools.json` 自动加载) | `workspace/tools.json` | | **SubAgent** | `content-writer` 撰稿员(程序化声明,自动注册 spawn 委派工具) | `WeChatPublisher.java` + `workspace/subagents/content-writer.md` | | **Function Call (@Tool)** | `estimate_readtime` / `render_wechat_html` / `validate_wechat_html` / `publish_to_wechat` | `PublisherToolkit.java` | | **发布闭环(可选)** | `publish_to_wechat` → exomind `POST /drafts` 注入正文 + `draft wechat` 调微信草稿箱(`PUBLISH_ACCOUNT` 门控) | `PublisherToolkit.java` | ## 几个源码核实出来的关键决策(避坑) 1. **DeepSeek 不能用 `.model("deepseek:...")`**:`agentscope-core` 的 `DeepSeekCredential.getChatModelClass()` 故意抛 `UnsupportedOperationException`,源码注释钦定「用 `OpenAIChatModel` 指向 DeepSeek base URL」。所以 pipeline 用 `OpenAIChatModel.builder().apiKey(...).baseUrl("https://api.deepseek.com").modelName("deepseek-chat")`。 2. **排版引擎是 Java `@Tool` 而不是 shell 脚本**:`HarnessAgent` 默认**只在沙箱文件系统下注册 shell 工具**(源码 `HarnessAgent.java:2326`),本地运行没有 shell,跑不了 python 脚本。所以把 doocs/md 规则的确定性渲染实现为 `render_wechat_html` Java 工具,Skill 负责知识、@Tool 负责引擎。 3. **SubAgent 必须程序化声明**:纯 `HarnessAgent.builder().workspace()` **不会**自动扫描 `subagents/*.md`(`build()` 里 `subagentDeclarations` 仅由 `.subagent(...)` 填充)。所以 pipeline 在 Java 里用 `SubagentDeclaration.builder()...inlineAgentsBody(...)` 声明 content-writer;`subagents/content-writer.md` 仅作人类可读规格存档。 4. **workspace 引导**:skills / tools.json 由 HarnessAgent 从 workspace 自动加载,但 workspace 必须是可写路径(要写 session/memory/产物)。pipeline 启动时把 `resources/workspace/*` 以 copy-if-absent 复制到 `.agentscope/workspace/`。 ## 跑法 前置: - JDK 17+、Maven 3.9+ - 已安装 exomind CLI(`which exomind` 能找到,提供 `exomind mcp` stdio 服务) - DeepSeek API Key ```bash cp .env.example .env # 编辑 .env 填入 DEEPSEEK_API_KEY source .env # 编译 mvn -q compile # 跑(默认选题:介绍 AgentScope Java Harness) mvn exec:java # 或自带选题 mvn exec:java -Dexec.args="写一篇讲 RAG 在企业落地踩坑的公众号文章" # 闭环投递到公众号草稿箱:设 PUBLISH_ACCOUNT 后,pipeline 末尾自动调 publish_to_wechat # export PUBLISH_ACCOUNT=ailang # ailang/danxin/mingdeng,需 exomind 已 login ``` 运行时会实时打印模型的流式文本和每次 `🔧 工具调用`(function call 可见)。产物: - `.agentscope/workspace/publisher/output/article.html` —— doocs/md 内联样式 HTML(可手动粘公众号) - `.agentscope/workspace/output/agent_deliverable.md` —— agent 最终交付文本 - 设了 `PUBLISH_ACCOUNT` 时,还会把 Markdown 正文投到对应公众号草稿箱(不群发,后台手动发) > **发布闭环说明**:`publish_to_wechat` 发给 exomind 的是 **Markdown 正文**(exomind 负责最终渲染 + AI 出封面 + 调微信);本地 `article.html` 是我们 `render_wechat_html` 的 doocs/md 排版产物,供手动粘贴/核对,两者渲染路径独立。 ## 依赖 - `io.agentscope:agentscope-harness:2.0.0`(Maven Central,自动带 `agentscope-core`) - `io.agentscope:agentscope-extensions-model-openai:2.0.0`(DeepSeek 兼容) - `io.modelcontextprotocol.sdk:mcp:0.17.0`(exomind MCP stdio 客户端) - `org.commonmark:commonmark:0.22.0`(render_wechat_html 的 Markdown 解析) ## 多轮会话与记忆(Redis + MEMORY.md) AgentScope 的记忆分两层,本 demo 都开了: - **多轮会话(短期,按 sessionId)**:agent 实例调用间无状态,靠 `RuntimeContext(sessionId, userId)` 做 key。`REDIS_STATE=1` 时用 `RedisAgentStateStore`(Lettuce→localhost:6379)存 `AgentState`——多轮 + **跨进程重启**记得(默认 JsonFile 也行,Redis 更生产级、多副本可共享)。 - **跨会话长期(MEMORY.md)**:`compaction(30/10)`——会话超 30 条压缩蒸馏 → `workspace/memory/` → `MEMORY.md`,下一轮注入 system prompt。`memory_save`/`memory_get`/`memory_search` 工具 agent 可显式存取。 ```bash # 多轮 REPL(同 sessionId,写稿→改标题→加段落 连续 refine) INTERACTIVE=1 mvn exec:java INTERACTIVE=1 REDIS_STATE=1 SESSION_ID=my-article mvn exec:java # 跨重启也记得 ``` > **实测**:turn1 写稿起标题 → turn2 问「标题是什么」,零工具调用 1 秒直答召回(`messages=29` 从 Redis 加载);**全新 JVM 同 sessionId** 跨重启仍精确召回。多轮 + 跨重启双铁证。 ## 项目结构(重构后) 按 [addyosmani/agent-skills](https://github.com/addyosmani/agent-skills)(84K⭐)的 code-review/code-simplification/TDD 四 skill 重构过,职责分层: ``` src/main/java/io/agentscope/study/ WeChatPublisher.java 入口(编排):config→workspace→AgentFactory→run 163 行(原 324) PipelineConfig.java env 配置集中加载 107 行 AgentFactory.java AutoCloseable:构建 model+toolkit+平台下发+subagent+ agent + 管 RedisClient/GitSkillRepository 生命周期 199 行 PublisherToolkit.java 4 个自研 @Tool(estimate/render/validate/publish) 304 行 Json.java 共享 ObjectMapper(带 JavaTimeModule) src/test/java/io/agentscope/study/ PublisherToolkitTest.java 10 个单元测试(render/validate/estimate 纯函数) ``` 重构要点:① 主类拆分(main 只编排);② 资源用 try-with-resources 关(修 RedisClient/GitRepo 泄漏);③ 加 10 个单测(TDD 抓到并修了代码块 `
` 拿不到深色背景的真 bug);④ 共享 ObjectMapper、入参校验、validate 逻辑修正。`mvn test` 全过。 ## exomind:个人知识库 + 公众号写作投递引擎 本 pipeline 的 MCP 素材源用的是 **[exomind](https://youhuale.cn)**(网站:https://youhuale.cn )——一个个人知识库引擎: - **知识库**:通过 CLI / MCP / Skill 多层接入,把笔记、调研、经验沉淀成可检索的知识图谱;本 pipeline 里 agent 就是通过 exomind MCP 的 `query` / `search` 工具去取素材的(`workspace/tools.json` 里配的 `exomind mcp` stdio 服务)。 - **公众号写作投递**:内置写作引擎(基于知识库素材 + 号调性生成草稿)和投递链路(AI 出封面 + 调微信草稿箱),把「取素材 → 写稿 → 排版 → 投递」闭环。 - 安装:`npm install -g exomind` 后 `exomind install` 配置 MCP/skill。 > 本 pipeline 只用了 exomind 的 MCP 取素材能力;排版用的是自带 Skill + 自研 @Tool,投递未在本 pipeline 工程内闭环。 ## 平台下发 skill(动态分发 demo) 上面的 `wechat-format` 是**预置** skill(workspace 目录、build 时静态加载)。生产里更常见的是「agent 管理平台维护 skill 存储 → agent 拉取」的动态分发。AgentScope 把 skill 来源抽象成 `AgentSkillRepository`,官方提供 **Git / MySQL / PostgreSQL / Nacos** 等后端——docs 原话:**MySQL / PostgreSQL / Nacos 支持「管理后台 / 配置中心动态修改、立即生效」**。 本 demo 用 **Git 仓库**做最轻量的平台下发演示(无需 DB / Nacos 基础设施): ```bash # ① 初始化本地 git skill 仓(=「平台」维护的 skill 存储),下发初始 skill A bash setup-skill-store.sh export SKILL_GIT_URL=file:///Users/you/path/to/agentscope-skill-store # 用脚本输出的 URL # ② agent 从平台拉取 skill(GitSkillRepository,autoSync=true,每次读检查远端 HEAD 变化才 pull) PRINT_SKILLS_ONLY=1 mvn exec:java # → 📦 平台(git)下发的 skill: [platform-greet] # ③ 平台再下发一个 skill:往仓里 commit 一个新 SKILL.md(模拟控制台发布) cd $SKILL_STORE && mkdir -p skills/platform-recap && \ printf -- '---\nname: platform-recap\ndescription: 一句回顾\n---\n# 回顾\n' \ > skills/platform-recap/SKILL.md && git add -A && git commit -m "platform: 下发 platform-recap" # ④ agent 再拉一次 → 拿到新 skill PRINT_SKILLS_ONLY=1 mvn exec:java # → 📦 平台(git)下发的 skill: [platform-greet, platform-recap] ``` 设了 `SKILL_GIT_URL`(且不设 `PRINT_SKILLS_ONLY`)时,平台下发的 skill 会和 workspace 预置 skill 一起挂到 HarnessAgent,agent 即可按需加载使用。 > **动态化三层次**(源码核实):① **预置**——workspace 静态加载;② **平台下发**——Git/MySQL/PG/**Nacos** 仓,agent 每次 build/session 拉取,平台改了下次生效(Nacos 带 listener/`AiService` 最接近实时推送);③ **agent 自助创建**——`enableSkillManageTool` → `skill_manage`(`SkillManageTool.java:256`,6 个 action),运行时 CRUD,但同会话 catalog 静态、要下次 build 才进目录。换后端只换 `AgentSkillRepository` 实现,agent 主流程不动。 ## 平台下发 MCP(动态分发 demo) skill 有开箱的 Git/MySQL/PG/Nacos 仓库(见上),**MCP 没有专门的仓库扩展**——但原语齐全,平台下发 MCP 靠「读平台配置 + 注册原语」自己组装: - `Toolkit.registerMcpClient()` / `removeMcpClient()`——运行时增删 MCP(源码 `Toolkit.java:538/548`) - `McpServerRegistrar.register(toolkit, Map)`——静态 helper,阻塞注册(源码 `McpServerRegistrar.java:49`,内部 `buildAsync().block()`) 本 demo 把 MCP 配置也放进同一个 git 平台仓(`mcp-servers.json`),`MCP_FROM_PLATFORM=1` 时从它读 + 注册,并 `disableToolsConfig()`(workspace tools.json 不再自动加载)——MCP 也变成「平台下发、agent 拉取」: ```bash bash setup-skill-store.sh # 平台仓含 skills/ + mcp-servers.json(exomind) export SKILL_GIT_URL=file://.../agentscope-skill-store MCP_FROM_PLATFORM=1 PRINT_SKILLS_ONLY=1 mvn exec:java # → 📦 平台(git)下发的 MCP: [exomind],toolkit 含 query/search # 平台撤销:清空 mcp-servers.json 的 mcpServers + commit # → 再跑 → toolkit 无 query/search(MCP 没了) ``` > **skill vs MCP 的不对称**:skill 平台下发是 turnkey(4 个仓库后端),MCP 是 DIY(原语 + 你自己读平台配置)。这是 AgentScope 当前的一个真实缺口,也是给上游的好反馈点。生产里推荐把 `mcp-servers.json` 放 **Nacos config**(带 listener,平台改 → 近实时刷新 + 重新 registerMcpClient)。 ## 升级到生产形态(换仓库后端) 上面的 demo 用 Git 仓做平台下发。生产里更常见的是「管理后台在线编辑 skill、改完即生效」——**只换 `AgentSkillRepository` 实现,agent 主流程一行不改**: **MySQL(管理后台在线运营,改完即生效)** ```xml ``` ```java import com.zaxxer.hikari.HikariDataSource; import io.agentscope.core.skill.repository.mysql.MysqlSkillRepository; HikariDataSource ds = new HikariDataSource(); ds.setJdbcUrl("jdbc:mysql://localhost:3306/agentscope"); ds.setUsername("root"); ds.setPassword("***"); // 第二参数 createIfNotExist=true:自动建库建表 AgentSkillRepository repo = new MysqlSkillRepository(ds, true); ``` **PostgreSQL**:把上面换成 `PostgresSkillRepository`(构造同 `(DataSource, boolean)`),依赖 `agentscope-extensions-skill-postgresql-repository`。 **Nacos(配置中心,最接近实时推送)**:依赖 `agentscope-extensions-nacos-skill`。Nacos 2.x+ 的 `AiService` 原生支持 skill/工具注册,配合 listener 可做到平台发布 → agent 近实时感知。 ```java import com.alibaba.nacos.api.ai.AiService; import io.agentscope.core.nacos.skill.NacosSkillRepository; AiService aiService = /* Nacos AI 服务客户端 */; AgentSkillRepository repo = new NacosSkillRepository(aiService, "namespace-id"); ``` **挂到 agent(三种后端都一样)**: ```java HarnessAgent agent = HarnessAgent.builder() .name("wechat-publisher") // ... 其余配置不变 .skillRepository(repo) // 平台下发的 skill 从这里来 .build(); ``` > **选型**:Git = 版本管控 / PR review;MySQL / PG = 管理后台在线编辑、可与业务数据同事务;**Nacos = 配置中心动态下发,带 listener 最接近实时推送**。docs 原话:「MySQL / PostgreSQL / Nacos 动态修改、立即生效」。换后端只换 repo 实现——这就是这套架构解耦的关键,也是企业级 agent 平台「控制平面管 Skill」的落地形态。 ## 为什么「git 下发」算动态加载? 把 skill/MCP 放进 git 仓、agent 从 git 拉,听起来还是「静态文件」——它「动态」在哪?关键是和 **workspace 预置**对比着看: | 维度 | workspace 预置(静态) | git 仓下发(动态) | |---|---|---| | 内容住哪 | 打进 agent 的 workspace(部署产物的一部分) | 外部 git 仓(与 agent 部署**解耦**) | | 加/改一个 skill | 改 workspace 文件 + **重新构建/重新部署 agent** | 平台 commit 一笔,**agent 不用动** | | 多 agent 共享 | 每个 agent 各自打包一份 | 一个仓喂多个 agent,平台改一次全生效 | | 内容新鲜度 | 构建时冻结 | `GitSkillRepository(autoSync=true)` 每次读检查远端 HEAD、变了就 pull | 「动态」指的是:**资源在运行时从外部源解析,平台能不重部署 agent 就改变它的内容,且每个新任务都重新解析**。机制(源码核实): 1. **外部源**——skill/MCP 不 baked-in 到 agent 产物,repo 在运行时从 git 仓解析。 2. **每个 task 重新解析(关键)**——`HarnessSkillMiddleware.onSystemPrompt` 在**每次 `agent.call()`** 都跑(`DynamicSkillMiddleware.java:42` 注释「on every call()」、`ReActAgent.java:609`),它调 `skillsForCall → repo.getAllSkills()`(`HarnessSkillMiddleware.java:313`)。所以每个新任务都重读 repo。 3. **autoSync**——`GitSkillRepository(autoSync=true).getAllSkills()` 每次检查远端 HEAD、变了就 pull。 **闭环:跨任务的生命周期**—— ``` agent.build() 一次(repo 挂在 agent 实例上,长生命周期,不随任务销毁) task1 → call → onSystemPrompt → getAllSkills(autoSync: 拉平台当前状态) → 重建 catalog → 执行 task2 → call → onSystemPrompt → getAllSkills(autoSync: 平台在 task1→task2 间改了就 pull) → 重建 catalog → 执行 ……平台 = live source of truth,每个任务都咨询一次 ``` 回答两个常被问的问题: - **下一个任务到来,这个 skill 还在吗?** —— 在。agent 实例和 repo 是长生命周期的,不随任务驱逐;task 2/3 还能拿到。 - **动态加载的 skill 会影响新任务执行吗?** —— 会,而且是逐任务生效。平台在两任务之间 add / remove / 改 skill,下一个 task 重新解析时立刻看到新版本;task N 的 skill 集 = 平台在该 task 开始时的状态。 > **例外 `frozen`**:`HarnessSkillMiddleware.frozen(...)` 把 skill 集快照一次、之后不再 per-call 重读,给确定性场景(测试 / eval)用。 > > **诚实边界**:这是「**逐任务动态**」(每个 call 重新解析),不是「**单次推理中途热插拔**」(单次模型调用内 skill 集固定)。`skill_manage` 自建的 skill 写进可写的 `WorkspaceSkillRepository`,**和平台 repo 一样走 per-call `getAllSkills`**(可写 repo 同样每次 fresh glob)→ 下一个 task 同样进 catalog、可被 `load_skill_through_path` 加载,不是两套机制。 一句话:**workspace ≈ 编译期常量;git 下发 ≈ 逐任务从外部仓库重新解析、平台改动下个任务就生效**——这才是它配得上「动态」的原因。 ## 排版 skill 来源 排版知识参考 GitHub 上 star >1K 的 [**doocs/md**](https://github.com/doocs/md)(~12.9K star,最主流的微信 Markdown 排版器)的内联样式规则,编码进 `wechat-format` skill 与 `render_wechat_html` 工具。 io.agentscope agentscope-extensions-skill-mysql-repository ${agentscope.version}