从 Wiki 到 DAG:搞懂 Agent 工程中那些容易混淆的技术名词
最近在学习 Agent 工程和 Java CLI 开发时,接触到了不少看起来毫不相关的名词:
Wiki、LLM Wiki、Picocli、JLine 3、OkHttp、Jackson、DAG、Graph、Scheduler……
有些是 Java 开发库,有些是架构概念,还有些是知识管理和任务调度领域的术语。
刚开始看时,很容易把它们混在一起。例如,Picocli 和 JLine 3 都与命令行有关,它们是不是同一种东西?Graph 和 DAG 有什么区别?Agent Loop 和 DAG 又能不能结合?
这篇文章就从实际开发的角度,把这些概念串起来。最后,我们还会尝试把它们放进一个 Java 版 AI Coding Agent 的架构中,看看它们分别负责什么。
一、Wiki:不只是一个文档目录
Wiki,通常指一种可持续编辑、组织和关联知识的知识管理系统。
可以把它理解成一个能够互相链接的知识网站。
假设我们正在开发一个 Agent 项目,随着功能越来越多,会积累不少技术资料:
- Agent Loop 的运行原理
- Tool 和 Hook 的区别
- Agent Runtime 的架构
- 模型 API 的接入方式
- 项目模块的职责
- 常见问题和故障排查方法
如果这些内容只是零散地保存在聊天记录、Word 文档或 Markdown 文件中,后续查找和维护会比较麻烦。
这时候就可以建立一个 Wiki:
Agent-Wiki/ ├── Agent基础/ │ ├── Agent是什么.md │ ├── Agent-Loop.md │ └── Tool与Hook.md ├── 工程架构/ │ ├── Harness.md │ ├── Agent-Runtime.md │ └── 安全机制.md └── 开发指南/ ├── 模型接入.md └── 常见问题.md但 Wiki 不只是把 Markdown 文件放到同一个目录里。
它更强调知识之间的关联。
例如,在Agent-Loop.md中,可以链接到Tool与Hook.md。读者了解 Agent Loop 时,就能继续查看工具调用和生命周期钩子的相关知识。
Wiki 和普通文档有什么区别?
| 对比 | 普通文档 | Wiki |
|---|---|---|
| 主要用途 | 记录某个主题 | 组织一套知识体系 |
| 页面关系 | 可以相互独立 | 强调页面之间的关联 |
| 更新方式 | 通常由作者维护 | 可以多人持续协作 |
| 查找方式 | 搜索文件或文档 | 搜索页面、沿链接浏览 |
| 常见形式 | Word、PDF、Markdown | Git Wiki、内部知识站点 |
需要注意,Wiki 并不一定需要专门的软件。通过 Markdown、目录索引和页面链接,同样可以构建一个轻量级 Wiki。
二、LLM Wiki:让大语言模型使用知识库
接下来是 LLM Wiki。
LLM 是 Large Language Model,也就是大语言模型。
需要先说明:LLM Wiki 并不是一个定义统一的标准技术名词。不同项目可能用它指不同的功能或产品。
通常可以从两个角度理解:
- 面向 LLM 的 Wiki:将知识组织起来,让大语言模型能够检索和使用。
- LLM 辅助维护的 Wiki:利用模型整理资料、生成摘要、建立知识关联、更新页面等。
例如,我们向一个接入项目 Wiki 的 Agent 提问:
为什么我的 Agent 调用了工具之后,没有继续生成最终答案?
系统可以通过知识检索找到 Agent Loop、Tool Result、消息历史等相关资料,再将检索结果提供给 LLM,让模型结合这些内容回答。
一个可能的处理过程是:
用户提出问题 | v 识别问题中的关键概念 | v 检索 Wiki 知识页面 | v 提取相关知识片段 | v 组合用户问题与检索结果 | v 发送给 LLM | v 生成回答这里就会涉及另一个重要概念:RAG。
LLM Wiki、RAG、向量数据库有什么区别?
这几个概念很容易混淆,但它们解决的问题并不相同。
| 名词 | 解决的问题 | 举例 |
|---|---|---|
| Wiki | 知识如何组织和维护? | Agent-Loop.md |
| RAG | 如何检索资料并提供给模型? | 根据问题寻找相关文本 |
| 向量数据库 | 如何存储和检索向量? | Milvus、Qdrant、Chroma |
| LLM | 如何理解输入并生成回答? | 根据问题与资料组织答案 |
它们可以组合使用。
例如:
技术文档 | v 整理成 Wiki 页面 | v 文本切分 Chunk | v Embedding 向量化 | v 存入向量数据库 | v 用户提问 | v 检索相关知识 | v 交给 LLM 生成回答这个过程就可以构成一种 Wiki + RAG 的知识增强方案。
需要记住:Wiki 负责组织知识,RAG 负责检索增强生成,向量数据库负责向量存储和检索。它们不是同一种技术。
三、Picocli:Java 命令行框架
从这里开始,进入 Java 工程开发领域。
假设我们想开发一个 Java 版的 AI Coding Agent,暂时不做复杂的 Web 页面,而是采用 CLI(Command-Line Interface,命令行界面)作为主要交互方式。
希望用户能够这样使用:
mycoder--helpmycoder--versionmycoder chat mycoder run--fileMain.java mycoder config--modelclaude如果不使用框架,我们需要自己解析 Java 的args数组,判断用户传入了什么命令和参数,还需要处理参数缺失、类型错误、帮助信息等问题。
例如:
publicstaticvoidmain(String[]args){if(args.length==0){System.out.println("请输入命令");return;}if(args[0].equals("chat")){System.out.println("启动聊天");}}功能少时还可以接受,但命令越来越多,就容易堆积大量if-else。
Picocli 就是为了解决这些问题而设计的 Java 命令行应用框架。
一个简单示例
引入 Maven 依赖:
<dependency><groupId>info.picocli</groupId><artifactId>picocli</artifactId></dependency>版本可以由项目的依赖管理统一指定。
编写命令:
importpicocli.CommandLine;importpicocli.CommandLine.Command;importpicocli.CommandLine.Option;importjava.util.concurrent.Callable;@Command(name="mycoder",description="我的 AI 编程助手",mixinStandardHelpOptions=true)publicclassMyCoderimplementsCallable<Integer>{@Option(names={"-m","--model"},description="指定使用的模型")privateStringmodel="default";@OverridepublicIntegercall(){System.out.println("当前模型:"+model);return0;}publicstaticvoidmain(String[]args){intexitCode=newCommandLine(newMyCoder()).execute(args);System.exit(exitCode);}}执行:
mycoder--modelclaude输出:
当前模型:claude这里有几个关键部分:
@Command:声明这是一个命令。name:指定命令名称。@Option:声明命令行选项。names:允许使用短参数和长参数。call():参数解析完成后执行的业务逻辑。execute(args):解析参数并执行对应命令。
Picocli 的核心作用是:让开发者不必手动处理复杂的命令和参数解析。
在 Agent 项目中,它可以负责 CLI 命令入口,但不会自动帮你实现 Agent Loop 或工具调用。
四、JLine 3:让命令行程序拥有交互体验
既然 Picocli 能处理命令行,为什么还需要 JLine 3?
因为它们关注的并不是同一件事。
Picocli 更关注命令和参数解析。
JLine 3 更关注终端里的输入和交互体验。
例如,我们希望 MyCoder 启动后能够进入一个持续交互的会话:
MyCoder AI Coding Agent 输入 exit 退出 输入 /help 查看命令 mycoder> 帮我检查这个项目的登录模块 [Agent] 正在分析项目... [Agent] 正在读取登录模块... [Agent] 找到了 2 个潜在问题... mycoder>如果只使用 Java 原生的Scanner,我们可以实现简单输入:
Scannerscanner=newScanner(System.in);while(true){System.out.print("mycoder> ");Stringinput=scanner.nextLine();if("exit".equals(input)){break;}System.out.println("你输入了:"+input);}但随着使用体验要求提高,我们可能还需要:
- 使用方向键找回历史命令。
- 编辑当前输入内容。
- 自动补全命令。
- 支持更完善的终端输入控制。
JLine 3 就是用来增强这些终端交互能力的。
它可以帮助 Java 程序构建更接近成熟 CLI 工具的交互体验。
Picocli 和 JLine 3 的关系
| 对比 | Picocli | JLine 3 |
|---|---|---|
| 核心职责 | 命令和参数解析 | 终端交互 |
| 关注内容 | 命令、选项、子命令 | 输入、历史、补全 |
| 典型场景 | mycoder run --file xxx | mycoder>持续交互 |
| 是否可以配合 | 可以 | 可以 |
可以这样设计:
用户启动 MyCoder | v Picocli 解析启动命令 | v 执行 chat 子命令 | v JLine 进入交互会话 | v 持续读取用户输入 | v 提交给 Agent Runtime记住:
Picocli 负责理解用户启动程序时传入的命令,JLine 3 负责程序运行期间与用户持续交互。
五、OkHttp:Java 如何与 LLM API 通信?
前面解决了用户如何向程序输入问题。
接下来还有一个问题:
用户输入:
帮我分析一下这个 Java 项目。
MyCoder 如何把这个问题发送给远程的 LLM?
这就涉及 HTTP 网络通信。
OkHttp 是一个常用的 HTTP 客户端库,可以帮助 Java 程序向服务器发送请求并接收响应。
例如:
MyCoder | | HTTP Request v LLM API 服务 | | HTTP Response v MyCoder简单的 OkHttp 请求
引入依赖:
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId></dependency>下面是一个简单示例:
importokhttp3.OkHttpClient;importokhttp3.Request;importokhttp3.Response;publicclassHttpDemo{publicstaticvoidmain(String[]args)throwsException{OkHttpClientclient=newOkHttpClient();Requestrequest=newRequest.Builder().url("https://httpbin.org/get").get().build();try(Responseresponse=client.newCall(request).execute()){System.out.println("状态码:"+response.code());if(response.body()!=null){System.out.println(response.body().string());}}}}关键部分:
OkHttpClient:负责执行 HTTP 请求。Request.Builder():构建请求。.url():设置请求地址。.get():指定请求方法。.build():创建请求对象。.execute():同步执行请求。response.code():获取 HTTP 状态码。response.body():获取响应体。
OkHttp 在 LLM 项目中的作用
例如,调用一个兼容 OpenAI Chat Completions 协议的接口,通常需要发送:
POST /v1/chat/completions Content-Type: application/json Authorization: Bearer YOUR_API_KEY请求体:
{"model":"your-model","messages":[{"role":"user","content":"解释一下 Agent Loop"}]}OkHttp 负责把这个 HTTP 请求发送出去。
但它不负责理解 LLM 返回的内容,也不负责决定是否调用工具。
这些属于其他模块的职责。
真实项目还需要考虑超时、异常处理、重试、鉴权、连接复用和流式响应等问题。
六、Jackson:Java 对象与 JSON 的转换
OkHttp 解决了网络通信问题。
但服务器返回的数据通常是 JSON,而 Java 程序内部往往使用对象来组织数据。
这时就需要 Jackson。
Jackson 是 Java 生态中非常常见的 JSON 处理库。
它最核心的功能之一就是:
- Java 对象 → JSON
- JSON → Java 对象
这两个过程分别叫作序列化和反序列化。
1. Java 对象转 JSON
假设有一个请求类:
publicclassChatRequest{publicStringmodel;publicStringcontent;publicintmaxTokens;}使用 Jackson:
importcom.fasterxml.jackson.databind.ObjectMapper;publicclassJacksonDemo{publicstaticvoidmain(String[]args)throwsException{ChatRequestrequest=newChatRequest();request.model="my-model";request.content="解释 Agent Loop";request.maxTokens=1000;ObjectMappermapper=newObjectMapper();Stringjson=mapper.writeValueAsString(request);System.out.println(json);}}输出类似:
{"model":"my-model","content":"解释 Agent Loop","maxTokens":1000}这个过程叫作序列化。
也就是把 Java 对象转换成 JSON 字符串。
2. JSON 转 Java 对象
假设服务器返回:
{"model":"my-model","content":"Agent Loop 是一个迭代执行过程","maxTokens":1000}我们可以使用:
ObjectMappermapper=newObjectMapper();ChatRequestrequest=mapper.readValue(json,ChatRequest.class);System.out.println(request.content);Jackson 会把 JSON 中的数据映射到 Java 对象的属性中。
这个过程叫作反序列化。
3. Jackson 与 OkHttp 的关系
两者经常一起使用,但职责不同:
| 工具 | 负责什么 |
|---|---|
| OkHttp | 发送 HTTP 请求、接收响应 |
| Jackson | 处理 JSON 数据 |
可以简单理解为:
Java 请求对象 | v Jackson 序列化 | v JSON 请求体 | v OkHttp 发送 HTTP 请求 | v LLM API | v 返回 JSON 响应 | v Jackson 反序列化 | v Java 响应对象在 Agent 项目中,模型返回的数据还可能包含工具调用名称和参数。
例如:
{"tool":"read_file","arguments":{"path":"src/Main.java"}}Jackson 可以将数据解析为 Java 对象,但解析成功不代表可以直接执行。
Agent Runtime 仍然需要进行参数校验、权限检查和安全审批。
七、Graph:什么是图结构?
前面几个概念主要属于知识管理和 Java 开发库。
接下来进入另一个很重要的领域:任务编排。
先认识 Graph。
Graph 中文叫作图,由两种基本元素组成:
- Vertex / Node:顶点、节点。
- Edge:边,用来表示节点之间的连接关系。
例如:
A / \ B C \ / D可以把 A、B、C、D 看作任务,把连接它们的线看作任务之间的关系。
Graph 并不一定表示执行顺序,也不一定有方向。
它是一种通用的数据结构,可以用来描述很多关系:
- 社交网络中的用户关系。
- 计算机网络中的连接关系。
- 地图中的道路关系。
- 工作流中的任务依赖。
- Agent 之间的协作关系。
在软件工程中,Graph 不只是一个数学概念,也是一种非常重要的建模方式。
八、DAG:有向无环图
DAG 的全称是:
Directed Acyclic Graph。
中文是:有向无环图。
它可以理解为 Graph 的一种特殊形式。
DAG 拆开看:
- Directed:有向,边有方向。
- Acyclic:无环,不允许存在有向循环。
- Graph:图,由节点和边组成。
例如:
A → B → D \ ↑ → C ──┘这里的箭头表示依赖关系。
如果 B、C 都需要先完成,D 才能开始,那么 D 就依赖 B 和 C。
DAG 有什么用?
假设我们开发一个项目,需要完成以下任务:
- A:需求分析
- B:设计数据库
- C:设计 API
- D:开发后端
- E:开发前端
- F:联调测试
这些任务并不是全部都需要串行执行。
可能的关系是:
A:需求分析 | +------+------+ | | B:设计数据库 C:设计 API | | +------+------+ | D:开发后端 | E:开发前端 | F:测试这只是一个简化示意,实际依赖关系应根据项目拆分。
更重要的是,如果 B、C 没有依赖关系,那么它们可以考虑并行执行。
如果采用纯串行:
A → B → C → D那么 B、C 即使可以同时进行,也会被迫等待。
而 DAG 能够明确描述依赖关系,让调度系统判断:
- 哪些任务可以执行?
- 哪些任务还需要等待?
- 哪些任务可以并行?
- 哪些任务必须等其他任务完成?
DAG 的核心价值是表达任务依赖关系,为任务调度和并行执行提供依据。
什么是拓扑排序?
DAG 还有一个重要概念:拓扑排序(Topological Sort)。
它的作用是:
在满足所有依赖关系的前提下,计算一个合法的节点执行顺序。
例如:
A → B A → C B → D C → D那么下面两种顺序都是合法的:
A → B → C → DA → C → B → D因为 B、C 之间没有依赖关系。
如果按批次调度,也可以理解成:
第一批:A 第二批:B、C(并行执行) 第三批:D常见的拓扑排序算法有:
Kahn 算法
- 统计每个节点的入度。
- 找出入度为 0 的节点。
- 执行或移除节点。
- 更新其后继节点的入度。
- 不断重复,直到所有节点处理完毕。
如果最终还有节点无法处理,说明图中存在环。
DFS 算法
使用深度优先搜索,根据节点的完成顺序生成拓扑序列,也可以用于检测环。
九、Graph 和 DAG 有什么区别?
这两个概念容易混淆,核心区别在于 DAG 有更加严格的结构限制。
| 对比 | Graph | DAG |
|---|---|---|
| 中文 | 图 | 有向无环图 |
| 是否有方向 | 可以有,也可以无 | 必须有方向 |
| 是否允许有环 | 可以 | 不允许有向环 |
| 表达能力 | 通用关系 | 有依赖方向的无环关系 |
| 常见用途 | 网络、关系、路径 | 工作流、任务调度、构建依赖 |
可以记住:
DAG 是 Graph 的一种特殊形式,但 Graph 不一定是 DAG。
树也是 DAG 的特殊情况(将树的边按根到叶子的方向来看)。但 DAG 更灵活,一个节点可以同时依赖多个前置节点。
十、Scheduler:调度器到底负责什么?
有了 DAG,就能描述任务之间的依赖关系。
但 DAG 自己并不会执行任务。
这时候就需要 Scheduler,也就是调度器。
Scheduler 的主要职责是:
- 判断哪些任务已经满足执行条件。
- 选择合适的任务开始执行。
- 管理任务的执行状态。
- 分配并发资源。
- 等待任务完成。
- 推动后续依赖任务执行。
例如:
DAG 工作流 | v Scheduler 调度器 | +---- 判断依赖是否完成 | +---- 选择可执行任务 | +---- 分配执行资源 | +---- 等待执行结果 | +---- 更新任务状态 | v 执行后继任务举个例子:
A:分析需求 | +---+---+ | | B C | | +---+---+ | D假设 A 已经完成,Scheduler 就可以让 B、C 同时执行。
B、C 都成功完成后,D 才具备执行条件。
如果 B 失败了,Scheduler 还需要按照系统策略决定:
- 是否重试 B。
- 是否取消 D。
- 是否允许部分结果继续执行。
- 是否暂停整个工作流并等待人工处理。
这些都不是 DAG 本身决定的,而是调度和工作流执行策略的一部分。
DAG、Scheduler 和 Workflow 的关系
这三个概念也很容易混在一起:
| 名词 | 核心问题 | 作用 |
|---|---|---|
| Graph / DAG | 任务之间是什么关系? | 描述结构和依赖 |
| Workflow | 整个业务流程是什么? | 定义业务步骤与流程规则 |
| Scheduler | 什么时候执行哪个任务? | 负责调度 |
| Executor | 如何真正执行任务? | 调用具体的函数、工具或 Agent |
可以理解为:
- Workflow 描述业务流程。
- DAG 可以作为工作流的结构表达方式。
- Scheduler 根据依赖和资源安排执行。
- Executor 真正执行任务。
并不是所有 Workflow 都必须是 DAG。例如,有些工作流需要循环、动态分支、人工审批后重新进入之前的步骤,这些情况可能需要状态机或其他控制结构。
十一、Agent Loop 和 DAG:有什么区别?
最后回到 Agent 工程。
前面学习过 Agent Loop,它的基本形式是:
whileTrue:response=llm.generate(messages)ifnotresponse.tool_calls:breakresult=execute_tools(response.tool_calls)messages.append(result)它描述的是 Agent 的迭代执行过程:
LLM 决策 | v 调用 Tool | v 获取结果 | v 再次调用 LLM | v 继续执行而 DAG 描述的是任务之间的依赖关系:
任务 A / \ B C \ / 任务 D二者解决的问题不一样:
| 对比 | Agent Loop | DAG |
|---|---|---|
| 核心问题 | Agent 下一步做什么? | 任务之间如何依赖? |
| 主要机制 | 循环迭代 | 节点与有向边 |
| 是否天然无环 | 不一定 | 是 |
| 常见用途 | ReAct Agent | 多任务编排、并行工作流 |
特别要注意:
Agent Loop 不一定是 DAG。
ReAct Agent 可以持续进行多轮思考、工具调用和观察,直到任务完成或达到执行限制。
DAG 则要求有向无环,适合描述明确的任务依赖关系。
但它们完全可以结合。
DAG 编排多个 Agent,每个 Agent 内部运行 Agent Loop
假设用户要求:
分析这个 Java 项目,检查代码质量,并生成技术报告。
可以拆分为:
用户任务 | v 任务拆解 | DAG 工作流 | +-------+-------+ | | v v 代码分析 Agent 数据分析 Agent | | Agent Loop Agent Loop | | +-------+-------+ | v 结果汇总 Agent | Agent Loop | v 技术报告其中:
- DAG:描述几个 Agent 任务之间的依赖。
- Agent:负责完成分配的任务。
- Agent Loop:管理每个 Agent 内部的模型调用与工具执行。
- Scheduler:决定什么时候启动、等待和推进任务。
- Tool:提供实际操作能力。
这就是一种常见的多 Agent 编排思路。
十二、把这些技术放进一个 Java Agent 项目
现在把前面所有名词放在一起,看看它们在 MyCoder 这样的 Java CLI Coding Agent 中分别处于什么位置。
用户 | v Picocli / JLine 3 命令解析与终端交互 | v Agent Runtime | +---------+----------+ | | v v Agent Loop Wiki / RAG | 知识检索 | v Tool Registry | v 工具执行与安全检查 | v 模型客户端 Model Client | +-------------------+ | | v v OkHttp Jackson 网络通信 JSON 解析 | | +---------+---------+ | v LLM API如果进一步支持复杂任务拆解和多 Agent 协作,可以在 Agent Runtime 中加入:
Agent Runtime | Workflow Engine | DAG Graph | Scheduler | Agent Executors | +--------+--------+ | | | Agent A Agent B Agent C | | | Agent Loop Agent Loop Agent Loop这并不意味着每个 Java Agent 项目都必须引入这些组件。
它们是可根据业务复杂度逐步增加的能力:
- CLI 简单命令:Picocli。
- 交互式终端:JLine 3。
- 模型网络请求:OkHttp。
- JSON 请求响应:Jackson。
- 项目知识管理:Wiki。
- 文档检索增强:RAG。
- 多任务依赖:DAG。
- 业务流程编排:Workflow。
- 任务执行安排:Scheduler。
十三、最后总结:建立一张自己的技术名词地图
| 名词 | 所属领域 | 一句话理解 |
|---|---|---|
| Wiki | 知识管理 | 组织、关联和维护知识 |
| LLM Wiki | AI 知识系统 | 让 LLM 使用或辅助维护 Wiki 知识 |
| RAG | 检索增强生成 | 找到相关资料并提供给 LLM |
| Picocli | Java CLI | 解析命令和参数 |
| JLine 3 | Java CLI | 增强终端交互体验 |
| OkHttp | 网络通信 | 发送 HTTP 请求和接收响应 |
| Jackson | 数据处理 | Java 对象与 JSON 转换 |
| Graph | 数据结构 | 用节点和边表示关系 |
| DAG | 图结构 | 有向且无环的图 |
| Topological Sort | 图算法 | 计算满足依赖关系的执行顺序 |
| Workflow | 流程编排 | 描述业务任务如何流转 |
| Scheduler | 任务调度 | 决定什么时候执行哪个任务 |
| Executor | 任务执行 | 真正执行任务 |
| Agent Loop | Agent 运行机制 | 管理模型决策、工具执行和结果反馈 |
如果你正在学习 Agent 工程,我更建议按照下面的顺序逐步掌握:
- Java 工程基础:Jackson、OkHttp,理解数据转换与 HTTP 通信。
- CLI 开发:Picocli、JLine 3,理解命令行程序如何构建。
- 知识增强:Wiki、Embedding、向量数据库、RAG。
- 图结构与算法:Graph、DAG、拓扑排序。
- Agent 编排:Workflow、Scheduler、Executor、多 Agent 协作。
最后留一个值得思考的问题:
当一个用户提出复杂任务时,Agent 是应该通过 Agent Loop 自己不断决定下一步,还是先把任务拆成 DAG,再交给 Scheduler 调度多个 Agent 并行完成?
实际上,这并不是非此即彼的问题。简单、动态、需要不断根据观察调整方向的任务,适合 Agent Loop;依赖清晰、可拆分、需要并行执行的复杂任务,可以考虑 DAG 编排。成熟的 Agent 系统往往会把两者结合起来。
理解这些基础概念,才能真正看懂一个 Agent 系统是怎样从简单的 LLM 调用,逐渐发展成具备工具执行、知识检索、任务调度和多 Agent 协作能力的工程系统。