graphloom 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- graphloom-0.1.0/LICENSE +21 -0
- graphloom-0.1.0/PKG-INFO +301 -0
- graphloom-0.1.0/README.md +271 -0
- graphloom-0.1.0/pyproject.toml +53 -0
- graphloom-0.1.0/setup.cfg +4 -0
- graphloom-0.1.0/src/graphloom/__init__.py +30 -0
- graphloom-0.1.0/src/graphloom/config.py +56 -0
- graphloom-0.1.0/src/graphloom/graph_builder.py +149 -0
- graphloom-0.1.0/src/graphloom/model/__init__.py +23 -0
- graphloom-0.1.0/src/graphloom/model/artifact_manifest.py +131 -0
- graphloom-0.1.0/src/graphloom/model/base_tool_input.py +53 -0
- graphloom-0.1.0/src/graphloom/model/state.py +110 -0
- graphloom-0.1.0/src/graphloom/model/subagents.py +20 -0
- graphloom-0.1.0/src/graphloom/nodes/__init__.py +1 -0
- graphloom-0.1.0/src/graphloom/nodes/ai.py +168 -0
- graphloom-0.1.0/src/graphloom/nodes/compaction.py +296 -0
- graphloom-0.1.0/src/graphloom/nodes/find_fault.py +257 -0
- graphloom-0.1.0/src/graphloom/nodes/finish.py +18 -0
- graphloom-0.1.0/src/graphloom/nodes/history.py +87 -0
- graphloom-0.1.0/src/graphloom/nodes/interrupt_guard.py +27 -0
- graphloom-0.1.0/src/graphloom/nodes/tool.py +259 -0
- graphloom-0.1.0/src/graphloom/prompt/__init__.py +1 -0
- graphloom-0.1.0/src/graphloom/prompt/context_renderer.py +126 -0
- graphloom-0.1.0/src/graphloom/prompt/find_fault_system_prompt.py +29 -0
- graphloom-0.1.0/src/graphloom/prompt/message_builder.py +50 -0
- graphloom-0.1.0/src/graphloom/prompt/stack.py +47 -0
- graphloom-0.1.0/src/graphloom/prompt/system_prompt.py +129 -0
- graphloom-0.1.0/src/graphloom/skills/__init__.py +4 -0
- graphloom-0.1.0/src/graphloom/skills/loader.py +128 -0
- graphloom-0.1.0/src/graphloom/tools/__init__.py +1 -0
- graphloom-0.1.0/src/graphloom/tools/artifact.py +414 -0
- graphloom-0.1.0/src/graphloom/tools/dispatch.py +374 -0
- graphloom-0.1.0/src/graphloom/util/__init__.py +1 -0
- graphloom-0.1.0/src/graphloom/util/message_utils.py +13 -0
- graphloom-0.1.0/src/graphloom/util/session_store.py +47 -0
- graphloom-0.1.0/src/graphloom/util/token_counter.py +73 -0
- graphloom-0.1.0/src/graphloom.egg-info/PKG-INFO +301 -0
- graphloom-0.1.0/src/graphloom.egg-info/SOURCES.txt +40 -0
- graphloom-0.1.0/src/graphloom.egg-info/dependency_links.txt +1 -0
- graphloom-0.1.0/src/graphloom.egg-info/requires.txt +11 -0
- graphloom-0.1.0/src/graphloom.egg-info/top_level.txt +1 -0
- graphloom-0.1.0/tests/test_smoke.py +48 -0
graphloom-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 xzhao32
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
graphloom-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: graphloom
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A minimal generic agent-loop framework on top of LangGraph: build_agent_graph assembles a standard ReAct loop (ai / tool / history / compaction / finish) with dependency-injected llm, checkpointer, tools, and runtime_context.
|
|
5
|
+
Author: xzhao32
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: langgraph,agent,llm,framework,react,langchain
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: langchain-core>=0.3
|
|
20
|
+
Requires-Dist: langgraph>=0.2
|
|
21
|
+
Requires-Dist: langchain-openai>=0.2
|
|
22
|
+
Requires-Dist: pydantic>=2
|
|
23
|
+
Requires-Dist: tenacity>=8
|
|
24
|
+
Requires-Dist: tiktoken>=0.7
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
<div align="center">
|
|
32
|
+
|
|
33
|
+
**中文** · [English](README.en.md)
|
|
34
|
+
|
|
35
|
+
# graphloom
|
|
36
|
+
|
|
37
|
+
**一个循环,织进你所有的 agent。**
|
|
38
|
+
|
|
39
|
+
构建在 [LangGraph](https://github.com/langchain-ai/langgraph) 之上的通用智能体框架。一个 `build_agent_graph` 就把一个具备完整循环、短期记忆、上下文压缩、断点续跑、子 agent 编排和技能渐进加载的 ReAct agent 装配出来——LLM、工具、检查点全部依赖注入,与传输层和业务无关。
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+

|
|
43
|
+

|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 目录
|
|
51
|
+
|
|
52
|
+
- [为什么是 graphloom](#为什么是-graphloom)
|
|
53
|
+
- [亮点](#亮点)
|
|
54
|
+
- [安装](#安装)
|
|
55
|
+
- [快速上手](#快速上手)
|
|
56
|
+
- [核心模型:循环如何流转](#核心模型循环如何流转)
|
|
57
|
+
- [智能体的记忆](#智能体的记忆)
|
|
58
|
+
- [技能:渐进式加载](#技能渐进式加载)
|
|
59
|
+
- [子 agent 编排](#子-agent-编排)
|
|
60
|
+
- [观察者节点](#观察者节点)
|
|
61
|
+
- [交付审阅:找茬节点](#交付审阅找茬节点)
|
|
62
|
+
- [产物通信](#产物通信)
|
|
63
|
+
- [`build_agent_graph` 参数](#build_agent_graph-参数)
|
|
64
|
+
- [运行时上下文](#运行时上下文)
|
|
65
|
+
- [框架内 / 框架外](#框架内--框架外)
|
|
66
|
+
- [示例:编码 agent](#示例编码-agent)
|
|
67
|
+
- [项目布局](#项目布局)
|
|
68
|
+
- [项目状态](#项目状态)
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 为什么是 graphloom
|
|
73
|
+
|
|
74
|
+
搭一个能用的 agent,真正的难点从来不是"调一次 LLM",而是那一圈**循环里的琐事**:如何跨轮记住进度、上下文撑爆窗口怎么办、任务中断了怎么续、要拆子任务并行怎么调度、复杂工作流的最佳实践怎么复用。
|
|
75
|
+
|
|
76
|
+
graphloom 把这些"每个正经 agent 都要重写一遍"的东西沉淀成一个可复用的循环。你只带来 LLM、系统提示词和工具——其余的循环机制它替你织好。它**不绑定**任何传输协议、任何数据库、任何前端;这些通过依赖注入接入。
|
|
77
|
+
|
|
78
|
+
## 亮点
|
|
79
|
+
|
|
80
|
+
- **通用 ReAct 循环** —— `observer → ai → tool → history → compaction` 一圈到底,收尾即停。一次调用装配完成。
|
|
81
|
+
- **短期记忆** —— 每一步都沉淀 `last_step_review / working_notes / next_action` 三段结构化思维链,累积成可回溯的步骤流,贯穿整个会话。
|
|
82
|
+
- **上下文压缩(memory compaction)** —— 估算 token 逼近窗口上限时,自动把早期步骤**无损折叠**成一条归档摘要(关键事实逐字保留:ID、URL、约束、报错、决策),长任务永不爆上下文。
|
|
83
|
+
- **断点续跑** —— 注入 checkpointer 即获得持久化;用户主动暂停时在最近检查点挂起,`ainvoke(None)` 原地续跑,状态零丢失。
|
|
84
|
+
- **子 agent 编排** —— 分组并行派发子任务,组间顺序、组内并发,产物清单在父子图之间滚动合并,父图检查点自动透传。
|
|
85
|
+
- **技能渐进加载** —— Claude Code 式的 skill 机制:先只给 agent 一份技能清单,任务需要时才按需读入完整工作流,系统提示词保持精简。
|
|
86
|
+
- **观察者节点(observer)** —— 可选的入口节点,每轮在 ai 之前运行,把最新外部状态注入当轮上下文。它只影响**当前这一轮**,不写进步骤流、不进记忆——用来喂实时信号(环境变化、用户旁路引导),而不污染历史。
|
|
87
|
+
- **交付物系统 + 三级审阅** —— 内置 artifact 工具做产出与收尾;收尾时可串联 `custom_find_fault`(你的自定义审阅)与 `find_fault`(内置质检)两道关卡,任一不合格就打回重做,通过才交付。
|
|
88
|
+
- **产物通信(artifact manifest)** —— 三条产物清单以不同合并语义在 agent、子 agent 与外界之间流转,是结构化的交付与交接通道。
|
|
89
|
+
- **传输无关 · 全注入** —— HITL、可观测性、持久化、LLM 供应商全部外置。框架零宿主耦合,只依赖 LangGraph / LangChain。
|
|
90
|
+
|
|
91
|
+
## 安装
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install graphloom
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
从源码开发:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install -e ".[dev]" # 含 pytest / pytest-asyncio / ruff
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
运行时依赖:`langchain-core`、`langgraph`、`langchain-openai`、`pydantic`、`tenacity`、`tiktoken`。
|
|
104
|
+
|
|
105
|
+
## 快速上手
|
|
106
|
+
|
|
107
|
+
给一个 LLM、一段系统提示词、一组工具,`build_agent_graph` 就还你一张编译好的 LangGraph,`ainvoke` 即跑:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import asyncio
|
|
111
|
+
from langchain_openai import ChatOpenAI
|
|
112
|
+
from graphloom import build_agent_graph, build_initial_agent_state
|
|
113
|
+
|
|
114
|
+
graph = build_agent_graph(
|
|
115
|
+
custom_system_prompt="You are a helpful agent.",
|
|
116
|
+
tools=[...], # 你的工具
|
|
117
|
+
llm=ChatOpenAI(model="gpt-4o-mini"),
|
|
118
|
+
allow_direct_reply=True, # 允许纯文本回复直接收尾
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
state = build_initial_agent_state(input_query="总结这个仓库", session_id="s1")
|
|
122
|
+
result = asyncio.run(graph.ainvoke(state))
|
|
123
|
+
print(result["final_reply"])
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 核心模型:循环如何流转
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
┌─────────────────────── 未收尾,继续 ───────────────────────┐
|
|
130
|
+
│ │
|
|
131
|
+
observer? → ai → tool ──route──→ history → compaction ────────────────→ ai
|
|
132
|
+
│
|
|
133
|
+
└──end_tag=True──→ (find_fault?) ──→ finish ──→ END
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- **ai** 调用 LLM,流式合并响应,记录一个 pending step(含三段思维链)。
|
|
137
|
+
- **tool** 执行 LLM 请求的工具调用;若无工具调用且 `allow_direct_reply=True`,以纯文本回复收尾。
|
|
138
|
+
- **route** 看 `end_tag`:为真走向收尾(可选先经审阅),否则回 history 继续。
|
|
139
|
+
- **history** 把工具结果折进一条完成态 step。
|
|
140
|
+
- **compaction** 当估算 token 超阈值时,把早期步骤无损折叠成摘要。
|
|
141
|
+
- **finish** 收束交付物,标记 `agent_status=done`。
|
|
142
|
+
|
|
143
|
+
**收尾契约**:任何工具把 `end_tag=True` 写进返回即可结束循环。内置 `deliver_artifact` 是规范做法;纯对话型 agent 用 `allow_direct_reply=True` 走直接回复。
|
|
144
|
+
|
|
145
|
+
## 智能体的记忆
|
|
146
|
+
|
|
147
|
+
graphloom 的记忆不是外挂的向量库,而是**循环状态本身**:
|
|
148
|
+
|
|
149
|
+
- **每步三段式思维链** —— agent 每一步都产出 `last_step_review`(复盘上一步成败)、`working_notes`(记录进度与关键事实)、`next_action`(下一步动作)。这逼着模型显式反思、显式记账,是抗跑偏、抗遗忘的核心。
|
|
150
|
+
- **步骤流即记忆** —— 这些步骤累积成 `past_steps`,随 checkpointer 持久化,跨轮、跨会话都在。渲染回提示词时以 `<agent_history>` 呈现,agent 始终看得见自己走过的路。
|
|
151
|
+
- **压缩而非截断** —— 上下文逼近上限时,`compaction` 节点把最早的步骤交给 LLM 折成一条"无损归档"摘要——数字、ID、URL、用户约束、报错与其解决方式逐字保留,只压缩冗余叙述。近几步始终保持原样。于是长任务能一直跑下去,而不是简单丢掉旧历史。
|
|
152
|
+
|
|
153
|
+
## 技能:渐进式加载
|
|
154
|
+
|
|
155
|
+
技能(skill)是一个含 `SKILL.md` 的目录,front-matter 声明 `name` 与 `description`。agent 一开始只看到技能的**名字+描述+位置**清单;真正需要时才用 `read_artifact` 读入完整工作流,及其引用的脚本/参考。这样既给了 agent 一菜单可复用的深度流程,又不让系统提示词膨胀。
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
graph = build_agent_graph(
|
|
159
|
+
custom_system_prompt=PROMPT,
|
|
160
|
+
tools=[...],
|
|
161
|
+
llm=llm,
|
|
162
|
+
available_skills=["pdf_extraction", "sql_report"], # 白名单
|
|
163
|
+
skills_dir="/path/to/your/skills", # 你的技能库,框架不写死
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
技能库放哪由你决定——`skills_dir` 注入即可,框架对内容一无所知。
|
|
168
|
+
|
|
169
|
+
## 子 agent 编排
|
|
170
|
+
|
|
171
|
+
配置 `subagents` 后,框架自动注入一个 `dispatch_subagents` 工具,让主 agent 把下一阶段拆成分组计划:**组间按 `group_id` 升序串行、组内并行**,上游产物滚动喂给下游,父图的 checkpointer 自动透传给每个子图。
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from graphloom import SubAgentSpec
|
|
175
|
+
|
|
176
|
+
graph = build_agent_graph(
|
|
177
|
+
custom_system_prompt=PROMPT,
|
|
178
|
+
tools=[...],
|
|
179
|
+
llm=llm,
|
|
180
|
+
subagents=[
|
|
181
|
+
SubAgentSpec(agent_name="researcher", description="调研并取证", factory=make_researcher),
|
|
182
|
+
SubAgentSpec(agent_name="writer", description="撰写报告", factory=make_writer),
|
|
183
|
+
],
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## 观察者节点
|
|
188
|
+
|
|
189
|
+
`observer` 是一个可选的自定义节点。配置后它成为图的入口,且每一轮都在 `ai` 之前运行(`compaction → observer → ai`)。它的职责是把**最新的外部状态**注入当轮——环境快照、用户在旁路发来的实时引导、外部系统的信号等。
|
|
190
|
+
|
|
191
|
+
它写入的 `observer_message_parts` 字段**没有累积语义**:每轮整体覆盖,只拼进当轮发给 LLM 的消息,**不写进 `past_steps`、不进记忆**。这是刻意的——观察者反映"此刻的世界",一旦过时就该被新观察取代,而不是沉淀成历史噪声。
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
async def observer(state):
|
|
195
|
+
snapshot = await read_live_environment(state["session_id"])
|
|
196
|
+
return {"observer_message_parts": [HumanMessage(content=f"[实时状态]\n{snapshot}")]}
|
|
197
|
+
|
|
198
|
+
graph = build_agent_graph(custom_system_prompt=PROMPT, tools=[...], llm=llm, observer=observer)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## 交付审阅:找茬节点
|
|
202
|
+
|
|
203
|
+
agent 标记收尾(`end_tag=True`)后,交付物在真正 finish 之前可以先过审阅关卡。graphloom 支持两级、可叠加:
|
|
204
|
+
|
|
205
|
+
- **`custom_find_fault`** —— 你自己的审阅节点,先运行。想接入任何外部校验(跑测试、schema 校验、业务规则)就放这里。
|
|
206
|
+
- **`find_fault`** —— 内置的 LLM 自审节点。传入一段审阅提示词,它会读交付物内容、对照原始请求做结构化质检,输出是否合格 + 缺陷清单 + 返工建议。
|
|
207
|
+
|
|
208
|
+
路由:`end_tag → custom_find_fault?(有则先跑)→ find_fault?(再跑)→ finish`。审阅**不合格**则清空交付清单、带着反馈**回到 history 让 agent 重做**;合格才放行到 finish。纯文本交付(无产物)被审阅节点视为放行。
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
graph = build_agent_graph(
|
|
212
|
+
custom_system_prompt=PROMPT, tools=[...], llm=llm,
|
|
213
|
+
custom_find_fault=my_test_runner_node, # 先跑:你的校验
|
|
214
|
+
find_fault="You are a strict reviewer. Verify every requirement is met.", # 后跑:LLM 自审
|
|
215
|
+
)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## 产物通信
|
|
219
|
+
|
|
220
|
+
agent 的产出不是塞进聊天记录,而是走**结构化产物清单(artifact manifest)**。state 里有三条清单,各有不同的合并语义,共同构成交付与交接通道:
|
|
221
|
+
|
|
222
|
+
| 清单 | 合并语义 | 含义 |
|
|
223
|
+
|---|---|---|
|
|
224
|
+
| `input_artifact_manifest` | 覆盖 | 外部/上游传入的参考产物 |
|
|
225
|
+
| `current_delivery_manifest` | 覆盖 | 本轮 `deliver_artifact` 提交、待审阅的产物 |
|
|
226
|
+
| `approved_artifact_manifest` | 合并去重 | 已通过审阅、可交付的产物;子 agent 的产物也滚动并入这里 |
|
|
227
|
+
|
|
228
|
+
内置 artifact 工具(`write / read / patch / deliver`)读写这些清单,`deliver_artifact` 把 `end_tag=True` 与 `current_delivery_manifest` 一起写入触发收尾。子 agent 编排时,上游的 `approved_artifact_manifest` 会作为下游的 `input_artifact_manifest` 喂进去——产物就是 agent 之间的交接语言。
|
|
229
|
+
|
|
230
|
+
## `build_agent_graph` 参数
|
|
231
|
+
|
|
232
|
+
| 参数 | 类型 | 默认 | 说明 |
|
|
233
|
+
|---|---|---|---|
|
|
234
|
+
| `custom_system_prompt` | `str` | 必填 | agent 的系统提示词;与框架通用提示词拼接。 |
|
|
235
|
+
| `tools` | `list` | 必填 | 你的 LangChain 工具。内置 artifact 工具自动注入(重名以你的为准)。 |
|
|
236
|
+
| `llm` | `BaseChatModel` | 必填 | 任意 LangChain 聊天模型;ai 与 compaction 节点共用。 |
|
|
237
|
+
| `find_fault` | `str \| callable` | `None` | 传字符串则用该提示词装配交付物自审节点;传节点则直接用。 |
|
|
238
|
+
| `custom_find_fault` | `callable` | `None` | 你自己的审阅节点,先于 `find_fault` 运行。 |
|
|
239
|
+
| `observer` | `callable` | `None` | 每轮 ai 之前运行的节点(注入外部观测/引导)。 |
|
|
240
|
+
| `subagents` | `list[SubAgentSpec]` | `None` | 配置后自动注入 `dispatch_subagents` 做多 agent 编排。 |
|
|
241
|
+
| `checkpointer` | LangGraph saver | `None` | 状态持久化;同时透传给子图。 |
|
|
242
|
+
| `tool_filter` | `callable` | `None` | `(state, config) -> 隐藏工具名集合`,按轮动态裁剪工具。 |
|
|
243
|
+
| `allow_direct_reply` | `bool` | `False` | 允许 LLM 不调用工具、直接以文本回复收尾。 |
|
|
244
|
+
| `available_skills` | `list[str]` | `None` | 暴露给 agent 的技能白名单。 |
|
|
245
|
+
| `skills_dir` | `str` | `None` | 扫描 `*/SKILL.md` 的技能库目录。 |
|
|
246
|
+
|
|
247
|
+
## 运行时上下文
|
|
248
|
+
|
|
249
|
+
宿主通过 `config["configurable"]["runtime_context"]` 注入运行期依赖。框架**原样透传**给工具与子图,自身不解读:
|
|
250
|
+
|
|
251
|
+
| 键 | 用途 |
|
|
252
|
+
|---|---|
|
|
253
|
+
| `artifact_base_dir` | artifact 工具的工作区根目录(亦可用 `GRAPHLOOM_ARTIFACT_BASE_DIR` 环境变量)。 |
|
|
254
|
+
| `callbacks` | 传给子图的 LangGraph 回调(token 流式等观测)。 |
|
|
255
|
+
| `cancel_event` | `asyncio.Event`;置位后在最近检查点抛 `GraphInterrupt` 暂停。 |
|
|
256
|
+
| `user_id` | 会话归属标识,供工具使用。 |
|
|
257
|
+
|
|
258
|
+
## 框架内 / 框架外
|
|
259
|
+
|
|
260
|
+
| 框架内(graphloom 负责) | 框架外(你负责) |
|
|
261
|
+
|---|---|
|
|
262
|
+
| 循环与结构性节点 | 工具——含 HITL、澄清、任何业务工具 |
|
|
263
|
+
| `AgentState`、三段式思维链、上下文压缩 | 传输 / wire——ws 事件码、流式哨兵 |
|
|
264
|
+
| 内置 artifact 工具、可选 dispatch / find_fault | 可观测性——走 LangGraph 标准 `callbacks` |
|
|
265
|
+
| 技能渐进加载机制 | 技能内容——你的 `skills_dir` |
|
|
266
|
+
| 注入接缝:llm / checkpointer / tools / runtime_context | 持久化后端、LLM 供应商 |
|
|
267
|
+
|
|
268
|
+
## 示例:编码 agent
|
|
269
|
+
|
|
270
|
+
[`examples/coding_agent/`](examples/coding_agent/) 用约 60 行搭了一个 Claude Code / Codex 风格的编码 agent:`read_file`、`write_file`、`run_command` 三个工具接进 `build_agent_graph`,从 `.env` 读一个 OpenAI 兼容网关。
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
pip install -e ".[dev]" python-dotenv
|
|
274
|
+
cp .env.example .env # 填入 BASE_URL / OPENAI_API_KEY / MODEL
|
|
275
|
+
python -m examples.coding_agent.agent "创建 fizzbuzz.py 并运行它"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
agent 在沙箱工作区里读写文件、执行命令,验证结果后直接回复。`run_command` 会执行任意 shell——只在你信任的工作区里运行。
|
|
279
|
+
|
|
280
|
+
## 项目布局
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
src/graphloom/
|
|
284
|
+
__init__.py 公开 API:build_agent_graph / AgentState / SubAgentSpec / …
|
|
285
|
+
graph_builder.py 入口
|
|
286
|
+
config.py 可调项(压缩阈值、并发上限等)
|
|
287
|
+
model/ state、reducers、schema、子 agent 规格
|
|
288
|
+
nodes/ ai / tool / history / compaction / finish / find_fault / interrupt_guard
|
|
289
|
+
tools/ artifact(4 个工具)、dispatch(子 agent 编排)
|
|
290
|
+
prompt/ 系统提示词、提示词栈、上下文渲染、消息装配
|
|
291
|
+
skills/ 技能加载(SKILL.md 解析 + 渐进加载提示段)
|
|
292
|
+
util/ 消息工具、token 计数、会话存储
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## 项目状态
|
|
296
|
+
|
|
297
|
+
Alpha —— 从一套生产 agent 代码中抽取而来,正在泛化循环、剥离全部宿主耦合。1.0 之前 API 可能变动。核心循环、短期记忆、上下文压缩、子 agent 派发、技能加载均已用真实与桩 LLM 验证。
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
MIT
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
**中文** · [English](README.en.md)
|
|
4
|
+
|
|
5
|
+
# graphloom
|
|
6
|
+
|
|
7
|
+
**一个循环,织进你所有的 agent。**
|
|
8
|
+
|
|
9
|
+
构建在 [LangGraph](https://github.com/langchain-ai/langgraph) 之上的通用智能体框架。一个 `build_agent_graph` 就把一个具备完整循环、短期记忆、上下文压缩、断点续跑、子 agent 编排和技能渐进加载的 ReAct agent 装配出来——LLM、工具、检查点全部依赖注入,与传输层和业务无关。
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 目录
|
|
21
|
+
|
|
22
|
+
- [为什么是 graphloom](#为什么是-graphloom)
|
|
23
|
+
- [亮点](#亮点)
|
|
24
|
+
- [安装](#安装)
|
|
25
|
+
- [快速上手](#快速上手)
|
|
26
|
+
- [核心模型:循环如何流转](#核心模型循环如何流转)
|
|
27
|
+
- [智能体的记忆](#智能体的记忆)
|
|
28
|
+
- [技能:渐进式加载](#技能渐进式加载)
|
|
29
|
+
- [子 agent 编排](#子-agent-编排)
|
|
30
|
+
- [观察者节点](#观察者节点)
|
|
31
|
+
- [交付审阅:找茬节点](#交付审阅找茬节点)
|
|
32
|
+
- [产物通信](#产物通信)
|
|
33
|
+
- [`build_agent_graph` 参数](#build_agent_graph-参数)
|
|
34
|
+
- [运行时上下文](#运行时上下文)
|
|
35
|
+
- [框架内 / 框架外](#框架内--框架外)
|
|
36
|
+
- [示例:编码 agent](#示例编码-agent)
|
|
37
|
+
- [项目布局](#项目布局)
|
|
38
|
+
- [项目状态](#项目状态)
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 为什么是 graphloom
|
|
43
|
+
|
|
44
|
+
搭一个能用的 agent,真正的难点从来不是"调一次 LLM",而是那一圈**循环里的琐事**:如何跨轮记住进度、上下文撑爆窗口怎么办、任务中断了怎么续、要拆子任务并行怎么调度、复杂工作流的最佳实践怎么复用。
|
|
45
|
+
|
|
46
|
+
graphloom 把这些"每个正经 agent 都要重写一遍"的东西沉淀成一个可复用的循环。你只带来 LLM、系统提示词和工具——其余的循环机制它替你织好。它**不绑定**任何传输协议、任何数据库、任何前端;这些通过依赖注入接入。
|
|
47
|
+
|
|
48
|
+
## 亮点
|
|
49
|
+
|
|
50
|
+
- **通用 ReAct 循环** —— `observer → ai → tool → history → compaction` 一圈到底,收尾即停。一次调用装配完成。
|
|
51
|
+
- **短期记忆** —— 每一步都沉淀 `last_step_review / working_notes / next_action` 三段结构化思维链,累积成可回溯的步骤流,贯穿整个会话。
|
|
52
|
+
- **上下文压缩(memory compaction)** —— 估算 token 逼近窗口上限时,自动把早期步骤**无损折叠**成一条归档摘要(关键事实逐字保留:ID、URL、约束、报错、决策),长任务永不爆上下文。
|
|
53
|
+
- **断点续跑** —— 注入 checkpointer 即获得持久化;用户主动暂停时在最近检查点挂起,`ainvoke(None)` 原地续跑,状态零丢失。
|
|
54
|
+
- **子 agent 编排** —— 分组并行派发子任务,组间顺序、组内并发,产物清单在父子图之间滚动合并,父图检查点自动透传。
|
|
55
|
+
- **技能渐进加载** —— Claude Code 式的 skill 机制:先只给 agent 一份技能清单,任务需要时才按需读入完整工作流,系统提示词保持精简。
|
|
56
|
+
- **观察者节点(observer)** —— 可选的入口节点,每轮在 ai 之前运行,把最新外部状态注入当轮上下文。它只影响**当前这一轮**,不写进步骤流、不进记忆——用来喂实时信号(环境变化、用户旁路引导),而不污染历史。
|
|
57
|
+
- **交付物系统 + 三级审阅** —— 内置 artifact 工具做产出与收尾;收尾时可串联 `custom_find_fault`(你的自定义审阅)与 `find_fault`(内置质检)两道关卡,任一不合格就打回重做,通过才交付。
|
|
58
|
+
- **产物通信(artifact manifest)** —— 三条产物清单以不同合并语义在 agent、子 agent 与外界之间流转,是结构化的交付与交接通道。
|
|
59
|
+
- **传输无关 · 全注入** —— HITL、可观测性、持久化、LLM 供应商全部外置。框架零宿主耦合,只依赖 LangGraph / LangChain。
|
|
60
|
+
|
|
61
|
+
## 安装
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install graphloom
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
从源码开发:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install -e ".[dev]" # 含 pytest / pytest-asyncio / ruff
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
运行时依赖:`langchain-core`、`langgraph`、`langchain-openai`、`pydantic`、`tenacity`、`tiktoken`。
|
|
74
|
+
|
|
75
|
+
## 快速上手
|
|
76
|
+
|
|
77
|
+
给一个 LLM、一段系统提示词、一组工具,`build_agent_graph` 就还你一张编译好的 LangGraph,`ainvoke` 即跑:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import asyncio
|
|
81
|
+
from langchain_openai import ChatOpenAI
|
|
82
|
+
from graphloom import build_agent_graph, build_initial_agent_state
|
|
83
|
+
|
|
84
|
+
graph = build_agent_graph(
|
|
85
|
+
custom_system_prompt="You are a helpful agent.",
|
|
86
|
+
tools=[...], # 你的工具
|
|
87
|
+
llm=ChatOpenAI(model="gpt-4o-mini"),
|
|
88
|
+
allow_direct_reply=True, # 允许纯文本回复直接收尾
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
state = build_initial_agent_state(input_query="总结这个仓库", session_id="s1")
|
|
92
|
+
result = asyncio.run(graph.ainvoke(state))
|
|
93
|
+
print(result["final_reply"])
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 核心模型:循环如何流转
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
┌─────────────────────── 未收尾,继续 ───────────────────────┐
|
|
100
|
+
│ │
|
|
101
|
+
observer? → ai → tool ──route──→ history → compaction ────────────────→ ai
|
|
102
|
+
│
|
|
103
|
+
└──end_tag=True──→ (find_fault?) ──→ finish ──→ END
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- **ai** 调用 LLM,流式合并响应,记录一个 pending step(含三段思维链)。
|
|
107
|
+
- **tool** 执行 LLM 请求的工具调用;若无工具调用且 `allow_direct_reply=True`,以纯文本回复收尾。
|
|
108
|
+
- **route** 看 `end_tag`:为真走向收尾(可选先经审阅),否则回 history 继续。
|
|
109
|
+
- **history** 把工具结果折进一条完成态 step。
|
|
110
|
+
- **compaction** 当估算 token 超阈值时,把早期步骤无损折叠成摘要。
|
|
111
|
+
- **finish** 收束交付物,标记 `agent_status=done`。
|
|
112
|
+
|
|
113
|
+
**收尾契约**:任何工具把 `end_tag=True` 写进返回即可结束循环。内置 `deliver_artifact` 是规范做法;纯对话型 agent 用 `allow_direct_reply=True` 走直接回复。
|
|
114
|
+
|
|
115
|
+
## 智能体的记忆
|
|
116
|
+
|
|
117
|
+
graphloom 的记忆不是外挂的向量库,而是**循环状态本身**:
|
|
118
|
+
|
|
119
|
+
- **每步三段式思维链** —— agent 每一步都产出 `last_step_review`(复盘上一步成败)、`working_notes`(记录进度与关键事实)、`next_action`(下一步动作)。这逼着模型显式反思、显式记账,是抗跑偏、抗遗忘的核心。
|
|
120
|
+
- **步骤流即记忆** —— 这些步骤累积成 `past_steps`,随 checkpointer 持久化,跨轮、跨会话都在。渲染回提示词时以 `<agent_history>` 呈现,agent 始终看得见自己走过的路。
|
|
121
|
+
- **压缩而非截断** —— 上下文逼近上限时,`compaction` 节点把最早的步骤交给 LLM 折成一条"无损归档"摘要——数字、ID、URL、用户约束、报错与其解决方式逐字保留,只压缩冗余叙述。近几步始终保持原样。于是长任务能一直跑下去,而不是简单丢掉旧历史。
|
|
122
|
+
|
|
123
|
+
## 技能:渐进式加载
|
|
124
|
+
|
|
125
|
+
技能(skill)是一个含 `SKILL.md` 的目录,front-matter 声明 `name` 与 `description`。agent 一开始只看到技能的**名字+描述+位置**清单;真正需要时才用 `read_artifact` 读入完整工作流,及其引用的脚本/参考。这样既给了 agent 一菜单可复用的深度流程,又不让系统提示词膨胀。
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
graph = build_agent_graph(
|
|
129
|
+
custom_system_prompt=PROMPT,
|
|
130
|
+
tools=[...],
|
|
131
|
+
llm=llm,
|
|
132
|
+
available_skills=["pdf_extraction", "sql_report"], # 白名单
|
|
133
|
+
skills_dir="/path/to/your/skills", # 你的技能库,框架不写死
|
|
134
|
+
)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
技能库放哪由你决定——`skills_dir` 注入即可,框架对内容一无所知。
|
|
138
|
+
|
|
139
|
+
## 子 agent 编排
|
|
140
|
+
|
|
141
|
+
配置 `subagents` 后,框架自动注入一个 `dispatch_subagents` 工具,让主 agent 把下一阶段拆成分组计划:**组间按 `group_id` 升序串行、组内并行**,上游产物滚动喂给下游,父图的 checkpointer 自动透传给每个子图。
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from graphloom import SubAgentSpec
|
|
145
|
+
|
|
146
|
+
graph = build_agent_graph(
|
|
147
|
+
custom_system_prompt=PROMPT,
|
|
148
|
+
tools=[...],
|
|
149
|
+
llm=llm,
|
|
150
|
+
subagents=[
|
|
151
|
+
SubAgentSpec(agent_name="researcher", description="调研并取证", factory=make_researcher),
|
|
152
|
+
SubAgentSpec(agent_name="writer", description="撰写报告", factory=make_writer),
|
|
153
|
+
],
|
|
154
|
+
)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 观察者节点
|
|
158
|
+
|
|
159
|
+
`observer` 是一个可选的自定义节点。配置后它成为图的入口,且每一轮都在 `ai` 之前运行(`compaction → observer → ai`)。它的职责是把**最新的外部状态**注入当轮——环境快照、用户在旁路发来的实时引导、外部系统的信号等。
|
|
160
|
+
|
|
161
|
+
它写入的 `observer_message_parts` 字段**没有累积语义**:每轮整体覆盖,只拼进当轮发给 LLM 的消息,**不写进 `past_steps`、不进记忆**。这是刻意的——观察者反映"此刻的世界",一旦过时就该被新观察取代,而不是沉淀成历史噪声。
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
async def observer(state):
|
|
165
|
+
snapshot = await read_live_environment(state["session_id"])
|
|
166
|
+
return {"observer_message_parts": [HumanMessage(content=f"[实时状态]\n{snapshot}")]}
|
|
167
|
+
|
|
168
|
+
graph = build_agent_graph(custom_system_prompt=PROMPT, tools=[...], llm=llm, observer=observer)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## 交付审阅:找茬节点
|
|
172
|
+
|
|
173
|
+
agent 标记收尾(`end_tag=True`)后,交付物在真正 finish 之前可以先过审阅关卡。graphloom 支持两级、可叠加:
|
|
174
|
+
|
|
175
|
+
- **`custom_find_fault`** —— 你自己的审阅节点,先运行。想接入任何外部校验(跑测试、schema 校验、业务规则)就放这里。
|
|
176
|
+
- **`find_fault`** —— 内置的 LLM 自审节点。传入一段审阅提示词,它会读交付物内容、对照原始请求做结构化质检,输出是否合格 + 缺陷清单 + 返工建议。
|
|
177
|
+
|
|
178
|
+
路由:`end_tag → custom_find_fault?(有则先跑)→ find_fault?(再跑)→ finish`。审阅**不合格**则清空交付清单、带着反馈**回到 history 让 agent 重做**;合格才放行到 finish。纯文本交付(无产物)被审阅节点视为放行。
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
graph = build_agent_graph(
|
|
182
|
+
custom_system_prompt=PROMPT, tools=[...], llm=llm,
|
|
183
|
+
custom_find_fault=my_test_runner_node, # 先跑:你的校验
|
|
184
|
+
find_fault="You are a strict reviewer. Verify every requirement is met.", # 后跑:LLM 自审
|
|
185
|
+
)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 产物通信
|
|
189
|
+
|
|
190
|
+
agent 的产出不是塞进聊天记录,而是走**结构化产物清单(artifact manifest)**。state 里有三条清单,各有不同的合并语义,共同构成交付与交接通道:
|
|
191
|
+
|
|
192
|
+
| 清单 | 合并语义 | 含义 |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| `input_artifact_manifest` | 覆盖 | 外部/上游传入的参考产物 |
|
|
195
|
+
| `current_delivery_manifest` | 覆盖 | 本轮 `deliver_artifact` 提交、待审阅的产物 |
|
|
196
|
+
| `approved_artifact_manifest` | 合并去重 | 已通过审阅、可交付的产物;子 agent 的产物也滚动并入这里 |
|
|
197
|
+
|
|
198
|
+
内置 artifact 工具(`write / read / patch / deliver`)读写这些清单,`deliver_artifact` 把 `end_tag=True` 与 `current_delivery_manifest` 一起写入触发收尾。子 agent 编排时,上游的 `approved_artifact_manifest` 会作为下游的 `input_artifact_manifest` 喂进去——产物就是 agent 之间的交接语言。
|
|
199
|
+
|
|
200
|
+
## `build_agent_graph` 参数
|
|
201
|
+
|
|
202
|
+
| 参数 | 类型 | 默认 | 说明 |
|
|
203
|
+
|---|---|---|---|
|
|
204
|
+
| `custom_system_prompt` | `str` | 必填 | agent 的系统提示词;与框架通用提示词拼接。 |
|
|
205
|
+
| `tools` | `list` | 必填 | 你的 LangChain 工具。内置 artifact 工具自动注入(重名以你的为准)。 |
|
|
206
|
+
| `llm` | `BaseChatModel` | 必填 | 任意 LangChain 聊天模型;ai 与 compaction 节点共用。 |
|
|
207
|
+
| `find_fault` | `str \| callable` | `None` | 传字符串则用该提示词装配交付物自审节点;传节点则直接用。 |
|
|
208
|
+
| `custom_find_fault` | `callable` | `None` | 你自己的审阅节点,先于 `find_fault` 运行。 |
|
|
209
|
+
| `observer` | `callable` | `None` | 每轮 ai 之前运行的节点(注入外部观测/引导)。 |
|
|
210
|
+
| `subagents` | `list[SubAgentSpec]` | `None` | 配置后自动注入 `dispatch_subagents` 做多 agent 编排。 |
|
|
211
|
+
| `checkpointer` | LangGraph saver | `None` | 状态持久化;同时透传给子图。 |
|
|
212
|
+
| `tool_filter` | `callable` | `None` | `(state, config) -> 隐藏工具名集合`,按轮动态裁剪工具。 |
|
|
213
|
+
| `allow_direct_reply` | `bool` | `False` | 允许 LLM 不调用工具、直接以文本回复收尾。 |
|
|
214
|
+
| `available_skills` | `list[str]` | `None` | 暴露给 agent 的技能白名单。 |
|
|
215
|
+
| `skills_dir` | `str` | `None` | 扫描 `*/SKILL.md` 的技能库目录。 |
|
|
216
|
+
|
|
217
|
+
## 运行时上下文
|
|
218
|
+
|
|
219
|
+
宿主通过 `config["configurable"]["runtime_context"]` 注入运行期依赖。框架**原样透传**给工具与子图,自身不解读:
|
|
220
|
+
|
|
221
|
+
| 键 | 用途 |
|
|
222
|
+
|---|---|
|
|
223
|
+
| `artifact_base_dir` | artifact 工具的工作区根目录(亦可用 `GRAPHLOOM_ARTIFACT_BASE_DIR` 环境变量)。 |
|
|
224
|
+
| `callbacks` | 传给子图的 LangGraph 回调(token 流式等观测)。 |
|
|
225
|
+
| `cancel_event` | `asyncio.Event`;置位后在最近检查点抛 `GraphInterrupt` 暂停。 |
|
|
226
|
+
| `user_id` | 会话归属标识,供工具使用。 |
|
|
227
|
+
|
|
228
|
+
## 框架内 / 框架外
|
|
229
|
+
|
|
230
|
+
| 框架内(graphloom 负责) | 框架外(你负责) |
|
|
231
|
+
|---|---|
|
|
232
|
+
| 循环与结构性节点 | 工具——含 HITL、澄清、任何业务工具 |
|
|
233
|
+
| `AgentState`、三段式思维链、上下文压缩 | 传输 / wire——ws 事件码、流式哨兵 |
|
|
234
|
+
| 内置 artifact 工具、可选 dispatch / find_fault | 可观测性——走 LangGraph 标准 `callbacks` |
|
|
235
|
+
| 技能渐进加载机制 | 技能内容——你的 `skills_dir` |
|
|
236
|
+
| 注入接缝:llm / checkpointer / tools / runtime_context | 持久化后端、LLM 供应商 |
|
|
237
|
+
|
|
238
|
+
## 示例:编码 agent
|
|
239
|
+
|
|
240
|
+
[`examples/coding_agent/`](examples/coding_agent/) 用约 60 行搭了一个 Claude Code / Codex 风格的编码 agent:`read_file`、`write_file`、`run_command` 三个工具接进 `build_agent_graph`,从 `.env` 读一个 OpenAI 兼容网关。
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
pip install -e ".[dev]" python-dotenv
|
|
244
|
+
cp .env.example .env # 填入 BASE_URL / OPENAI_API_KEY / MODEL
|
|
245
|
+
python -m examples.coding_agent.agent "创建 fizzbuzz.py 并运行它"
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
agent 在沙箱工作区里读写文件、执行命令,验证结果后直接回复。`run_command` 会执行任意 shell——只在你信任的工作区里运行。
|
|
249
|
+
|
|
250
|
+
## 项目布局
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
src/graphloom/
|
|
254
|
+
__init__.py 公开 API:build_agent_graph / AgentState / SubAgentSpec / …
|
|
255
|
+
graph_builder.py 入口
|
|
256
|
+
config.py 可调项(压缩阈值、并发上限等)
|
|
257
|
+
model/ state、reducers、schema、子 agent 规格
|
|
258
|
+
nodes/ ai / tool / history / compaction / finish / find_fault / interrupt_guard
|
|
259
|
+
tools/ artifact(4 个工具)、dispatch(子 agent 编排)
|
|
260
|
+
prompt/ 系统提示词、提示词栈、上下文渲染、消息装配
|
|
261
|
+
skills/ 技能加载(SKILL.md 解析 + 渐进加载提示段)
|
|
262
|
+
util/ 消息工具、token 计数、会话存储
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## 项目状态
|
|
266
|
+
|
|
267
|
+
Alpha —— 从一套生产 agent 代码中抽取而来,正在泛化循环、剥离全部宿主耦合。1.0 之前 API 可能变动。核心循环、短期记忆、上下文压缩、子 agent 派发、技能加载均已用真实与桩 LLM 验证。
|
|
268
|
+
|
|
269
|
+
## License
|
|
270
|
+
|
|
271
|
+
MIT
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "graphloom"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A minimal generic agent-loop framework on top of LangGraph: build_agent_graph assembles a standard ReAct loop (ai / tool / history / compaction / finish) with dependency-injected llm, checkpointer, tools, and runtime_context."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "xzhao32" }]
|
|
13
|
+
keywords = ["langgraph", "agent", "llm", "framework", "react", "langchain"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"langchain-core>=0.3",
|
|
26
|
+
"langgraph>=0.2",
|
|
27
|
+
"langchain-openai>=0.2",
|
|
28
|
+
"pydantic>=2",
|
|
29
|
+
"tenacity>=8",
|
|
30
|
+
"tiktoken>=0.7",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
dev = [
|
|
35
|
+
"pytest>=7",
|
|
36
|
+
"pytest-asyncio>=0.21",
|
|
37
|
+
"ruff>=0.6",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.packages.find]
|
|
41
|
+
where = ["src"]
|
|
42
|
+
|
|
43
|
+
[tool.pytest.ini_options]
|
|
44
|
+
asyncio_mode = "auto"
|
|
45
|
+
testpaths = ["tests"]
|
|
46
|
+
|
|
47
|
+
[tool.ruff]
|
|
48
|
+
line-length = 120
|
|
49
|
+
target-version = "py310"
|
|
50
|
+
|
|
51
|
+
[tool.ruff.lint]
|
|
52
|
+
select = ["E", "F", "I"]
|
|
53
|
+
ignore = ["E501"]
|