tina-multi-agent 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.
@@ -0,0 +1,171 @@
1
+ Metadata-Version: 2.4
2
+ Name: tina-multi-agent
3
+ Version: 0.1.0
4
+ Summary: tina 的实验性多 Agent 场景(消息总线 + Web 调试控制台)
5
+ Author-email: 王出日 <wangchuri@163.com>
6
+ License: Apache Software License
7
+ Project-URL: Homepage, https://gitee.com/wang-churi/tina
8
+ Project-URL: Repository, https://gitee.com/wang-churi/tina.git
9
+ Project-URL: GitHub, https://github.com/XIMOCY/tina.git
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: Apache Software License
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: tina-python>=0.7.0
16
+ Requires-Dist: fastapi>=0.110
17
+ Requires-Dist: uvicorn>=0.29
18
+ Requires-Dist: websockets>=12
19
+ Provides-Extra: test
20
+ Requires-Dist: pytest>=9.0; extra == "test"
21
+ Requires-Dist: pytest-asyncio>=1.4; extra == "test"
22
+
23
+ # tina 多 Agent(实验性)
24
+
25
+ > **实验性功能**:API 可能随版本变动,建议用于原型验证与调试。生产环境请谨慎评估。
26
+ >
27
+ > 独立发行包 `tina-multi-agent`(import 名 `tina_multi_agent`),不并入 `tina-python` 主包;
28
+ > 主包需要时通过 `tina-python[multi-agent]` 安装它。
29
+
30
+ `tina_multi_agent` 让若干个各自独立的 `Agent`(含 `MultimodalAgent`)注册进一个「环境」,
31
+ 通过消息总线互相通信,并配一个 Web 调试控制台用于观测与介入。
32
+
33
+ ## 安装
34
+
35
+ ```bash
36
+ pip install tina-multi-agent
37
+ # 或由主包的可选依赖带入
38
+ pip install "tina-python[multi-agent]"
39
+ ```
40
+
41
+ Web 调试控制台(FastAPI + WebSocket)已作为本包的核心依赖自带,无需额外安装。
42
+
43
+ ## 文件结构
44
+
45
+ ```
46
+ packages/tina-multi-agent/tina_multi_agent/
47
+ ├── __init__.py # 导出 Message / MessageBus / MultiAgentEnvironment / MultiAgentWeb
48
+ ├── message.py # Message(消息结构)
49
+ ├── message_bus.py # MessageBus(队列 + 历史 + 入队监听器)
50
+ ├── environment.py # MultiAgentEnvironment(注册、分发、每个 Agent 的收信 worker)
51
+ └── web/
52
+ ├── server.py # MultiAgentWeb(FastAPI:HTTP + WebSocket)
53
+ └── static/index.html
54
+ ```
55
+
56
+ ## 快速开始
57
+
58
+ ```python
59
+ from tina import Agent
60
+ from tina.llm import BaseAPI
61
+ from tina_multi_agent import MultiAgentEnvironment, MultiAgentWeb
62
+
63
+ llm = BaseAPI()
64
+
65
+ env = MultiAgentEnvironment(name="room")
66
+ env.add_agent(Agent(llm=llm, name="alice", system_prompt="你是 alice,可用 send_message 和其他 Agent 交流"))
67
+ env.add_agent(Agent(llm=llm, name="bob", system_prompt="你是 bob,可用 send_message 和其他 Agent 交流"))
68
+
69
+ # 方式一:纯 headless
70
+ # env.run() 会在 start 后持续运行,直到 env.stop()(异步)
71
+ # import asyncio; asyncio.run(env.run())
72
+
73
+ # 方式二:带 Web 控制台(会自动启动环境)
74
+ MultiAgentWeb(env, port=7077).run()
75
+ ```
76
+
77
+ 启动后:
78
+
79
+ - 浏览器打开 `http://127.0.0.1:7077` 查看实时对话;
80
+ - 或程序内投放指令:
81
+ - `env.predict("开始工作")` —— 广播给所有 Agent;
82
+ - `env.predict("只给 alice", main_agent="alice")` —— 定向给某个 Agent。
83
+
84
+ Web 控制台所需的 FastAPI / uvicorn / websockets 已随本包自带。
85
+
86
+ ## 核心概念
87
+
88
+ - **注册**:`env.add_agent(agent, name=None)`,`name` 缺省用 `agent.name`。
89
+ - **通信工具**:`start()` 时自动给每个 Agent 注册 `send_message(content, recipient=None)`,
90
+ 工具描述里会列出环境内全部 Agent;`recipient` 省略即广播给其他所有 Agent。
91
+ - **消息总线**:`env.bus`,一个 `MessageBus`。`put` 入队并记录历史,`history()` 查询,
92
+ `add_listener(fn)` 可订阅「消息入队」事件。
93
+ - **收信 worker**:每个 Agent 一个专属收件队列;收到消息、且该 Agent 不在
94
+ `tool_calling` / `on_tool_confirm` / `error` 状态时,把消息注入其上下文并触发一次推理:
95
+ - 外部指令 → `add_user_message`;
96
+ - 同伴消息 → `assistant` + `name=发送者`(思考类模型会自动补 `reasoning_content=""`)。
97
+ - **回合中途注入**:Agent 正在输出时又来了消息,不会一直等到整个回合结束——环境给每个
98
+ Agent 挂了 `before_llm_call` 处理器(每轮 LLM 调用前触发),在「工具跑完、下一轮 LLM
99
+ 之前」这个安全边界把队列里的消息注入上下文,于是下一轮 LLM 就能看到它们。纯文本回合
100
+ 没有工具边界,消息会在回合结束后由 worker 起新回合处理。
101
+ - **生命周期**:`await env.start()` / `await env.stop()`;`await env.run()` 阻塞运行直到停止。
102
+ - **打断**:`env.interrupt(name)` 打断某个 Agent 当前输出,`env.interrupt_all()` 打断全部。
103
+ 打断会保留已流出的部分正文、补齐「被打断」的工具结果并复位状态(不会中止该 Agent 的收信循环)。
104
+ - **查询**:`env.agents`、`env.agent_names`、`env.history()`。
105
+
106
+ ## Message
107
+
108
+ ```python
109
+ Message(sender: str, content: str, recipient: str | None = None, role: str = "assistant")
110
+ ```
111
+
112
+ - `recipient=None` 表示广播;
113
+ - `role` 为 `"user"`(外部指令)或 `"assistant"`(Agent 之间)。
114
+
115
+ ## Web 控制台
116
+
117
+ ```python
118
+ MultiAgentWeb(
119
+ env,
120
+ host="127.0.0.1",
121
+ port=7077,
122
+ tool_confirmation="ask", # ask | allow | deny
123
+ confirm_timeout=300.0,
124
+ ).run()
125
+ ```
126
+
127
+ 页面能力:
128
+
129
+ - 左侧 Agent 列表(含「全部」);主区按 Agent 数量自适应网格,可同时看多个 Agent;
130
+ - 实时流式输出,推理内容灰显,工具调用渲染成卡片(名称 · 状态 / 参数 / 结果);
131
+ - 总线消息按方向显示:`◀ 发送者`(收到)、`▶ 收件人`(发出)、`指令`(外部);
132
+ - 底部输入框可选「广播」或定向发送;
133
+ - 每个 Agent 生成中会在面板右上角显示「■ 打断」,点击即可打断该 Agent 当前输出(等同 TUI 的 Esc);
134
+ - Markdown 正文用内置轻量渲染(零外部依赖)。
135
+
136
+ 对外接口:
137
+
138
+ - `GET /health` → `{ok, agents, running}`
139
+ - `POST /instruction`,body `{"content": str, "main_agent": str|null}` —— 供外部程序注入指令
140
+ - `WS /ws` —— 事件:`init / message / chunk / turn_end / interrupted / confirm / confirm_cancel / permissions / error`
141
+
142
+ ## 工具确认与权限
143
+
144
+ - `require_confirmation=True` 的工具执行前会弹窗确认(TUI 也支持同类机制)。
145
+ - 全局策略 `tool_confirmation`:`ask`(默认,弹窗)/ `allow`(全放行)/ `deny`(全拒绝)。
146
+ - 弹窗按钮:`允许 / 始终允许 / 拒绝 / 始终拒绝 / 全部允许 / 全部拒绝`。
147
+ - 权限表按 **(Agent, 工具)** 记 `allow` / `deny`,**内存态**(重启即清空)。
148
+ header「权限」窗口可可视化调整,支持「应用到所有 Agent」。
149
+ - 无前端在线时默认拒绝;确认超时(`confirm_timeout`)同样按拒绝处理。
150
+
151
+ ## 边界与注意事项
152
+
153
+ - **软约束**:星型拓扑、禁止广播等,需要写进各 Agent 的 `system_prompt`,框架不强制。
154
+ - **尚无消息深度上限**:Agent 间广播互聊会指数放大(实测一条广播可瞬间产生上千次推理)。
155
+ 建议用提示词约束,或后续加 `Message.depth` 硬边界来兜底。
156
+ - **权限内存态**:跨进程/重启不保留。
157
+ - **事件归属**:`on_stream_chunk`、`on_turn_end` 等由开发者或 Web 层自行挂载,环境本身不管理事件。
158
+ - **思考模型**:`enable_deepseek_reasoning_tools(agent)` 会给 Agent 打 `_reasoning_required` 标记,
159
+ 环境据此给注入的同伴消息补 `reasoning_content`,避免 DeepSeek 思考模式报 400。
160
+
161
+ ## 示例
162
+
163
+ 最小用法可直接参考上面的「快速开始」。更完整的示例(5 个 Agent 的演示、星型 QA 集群等)
164
+ 放在仓库的忽略目录 `little_toy/` 下,**不随 `tina-python` 包发布**。
165
+
166
+ ## 相关集成(可选)
167
+
168
+ - **opencode**:环境侧工具 `ask_opencode` 通过 opencode server 的**会话 API** 向 opencode 发消息;
169
+ opencode 侧可放自定义工具(`.opencode/tools/ask_qa.ts`)调用本服务的 `POST /instruction` 回投指令。
170
+ - **飞书 / Lark**:Agent → 飞书走官方 MCP(`@larksuiteoapi/lark-mcp`);
171
+ 飞书 → Agent 需要机器人事件订阅(建议用长连接 SDK)转发到 `POST /instruction`。
@@ -0,0 +1,149 @@
1
+ # tina 多 Agent(实验性)
2
+
3
+ > **实验性功能**:API 可能随版本变动,建议用于原型验证与调试。生产环境请谨慎评估。
4
+ >
5
+ > 独立发行包 `tina-multi-agent`(import 名 `tina_multi_agent`),不并入 `tina-python` 主包;
6
+ > 主包需要时通过 `tina-python[multi-agent]` 安装它。
7
+
8
+ `tina_multi_agent` 让若干个各自独立的 `Agent`(含 `MultimodalAgent`)注册进一个「环境」,
9
+ 通过消息总线互相通信,并配一个 Web 调试控制台用于观测与介入。
10
+
11
+ ## 安装
12
+
13
+ ```bash
14
+ pip install tina-multi-agent
15
+ # 或由主包的可选依赖带入
16
+ pip install "tina-python[multi-agent]"
17
+ ```
18
+
19
+ Web 调试控制台(FastAPI + WebSocket)已作为本包的核心依赖自带,无需额外安装。
20
+
21
+ ## 文件结构
22
+
23
+ ```
24
+ packages/tina-multi-agent/tina_multi_agent/
25
+ ├── __init__.py # 导出 Message / MessageBus / MultiAgentEnvironment / MultiAgentWeb
26
+ ├── message.py # Message(消息结构)
27
+ ├── message_bus.py # MessageBus(队列 + 历史 + 入队监听器)
28
+ ├── environment.py # MultiAgentEnvironment(注册、分发、每个 Agent 的收信 worker)
29
+ └── web/
30
+ ├── server.py # MultiAgentWeb(FastAPI:HTTP + WebSocket)
31
+ └── static/index.html
32
+ ```
33
+
34
+ ## 快速开始
35
+
36
+ ```python
37
+ from tina import Agent
38
+ from tina.llm import BaseAPI
39
+ from tina_multi_agent import MultiAgentEnvironment, MultiAgentWeb
40
+
41
+ llm = BaseAPI()
42
+
43
+ env = MultiAgentEnvironment(name="room")
44
+ env.add_agent(Agent(llm=llm, name="alice", system_prompt="你是 alice,可用 send_message 和其他 Agent 交流"))
45
+ env.add_agent(Agent(llm=llm, name="bob", system_prompt="你是 bob,可用 send_message 和其他 Agent 交流"))
46
+
47
+ # 方式一:纯 headless
48
+ # env.run() 会在 start 后持续运行,直到 env.stop()(异步)
49
+ # import asyncio; asyncio.run(env.run())
50
+
51
+ # 方式二:带 Web 控制台(会自动启动环境)
52
+ MultiAgentWeb(env, port=7077).run()
53
+ ```
54
+
55
+ 启动后:
56
+
57
+ - 浏览器打开 `http://127.0.0.1:7077` 查看实时对话;
58
+ - 或程序内投放指令:
59
+ - `env.predict("开始工作")` —— 广播给所有 Agent;
60
+ - `env.predict("只给 alice", main_agent="alice")` —— 定向给某个 Agent。
61
+
62
+ Web 控制台所需的 FastAPI / uvicorn / websockets 已随本包自带。
63
+
64
+ ## 核心概念
65
+
66
+ - **注册**:`env.add_agent(agent, name=None)`,`name` 缺省用 `agent.name`。
67
+ - **通信工具**:`start()` 时自动给每个 Agent 注册 `send_message(content, recipient=None)`,
68
+ 工具描述里会列出环境内全部 Agent;`recipient` 省略即广播给其他所有 Agent。
69
+ - **消息总线**:`env.bus`,一个 `MessageBus`。`put` 入队并记录历史,`history()` 查询,
70
+ `add_listener(fn)` 可订阅「消息入队」事件。
71
+ - **收信 worker**:每个 Agent 一个专属收件队列;收到消息、且该 Agent 不在
72
+ `tool_calling` / `on_tool_confirm` / `error` 状态时,把消息注入其上下文并触发一次推理:
73
+ - 外部指令 → `add_user_message`;
74
+ - 同伴消息 → `assistant` + `name=发送者`(思考类模型会自动补 `reasoning_content=""`)。
75
+ - **回合中途注入**:Agent 正在输出时又来了消息,不会一直等到整个回合结束——环境给每个
76
+ Agent 挂了 `before_llm_call` 处理器(每轮 LLM 调用前触发),在「工具跑完、下一轮 LLM
77
+ 之前」这个安全边界把队列里的消息注入上下文,于是下一轮 LLM 就能看到它们。纯文本回合
78
+ 没有工具边界,消息会在回合结束后由 worker 起新回合处理。
79
+ - **生命周期**:`await env.start()` / `await env.stop()`;`await env.run()` 阻塞运行直到停止。
80
+ - **打断**:`env.interrupt(name)` 打断某个 Agent 当前输出,`env.interrupt_all()` 打断全部。
81
+ 打断会保留已流出的部分正文、补齐「被打断」的工具结果并复位状态(不会中止该 Agent 的收信循环)。
82
+ - **查询**:`env.agents`、`env.agent_names`、`env.history()`。
83
+
84
+ ## Message
85
+
86
+ ```python
87
+ Message(sender: str, content: str, recipient: str | None = None, role: str = "assistant")
88
+ ```
89
+
90
+ - `recipient=None` 表示广播;
91
+ - `role` 为 `"user"`(外部指令)或 `"assistant"`(Agent 之间)。
92
+
93
+ ## Web 控制台
94
+
95
+ ```python
96
+ MultiAgentWeb(
97
+ env,
98
+ host="127.0.0.1",
99
+ port=7077,
100
+ tool_confirmation="ask", # ask | allow | deny
101
+ confirm_timeout=300.0,
102
+ ).run()
103
+ ```
104
+
105
+ 页面能力:
106
+
107
+ - 左侧 Agent 列表(含「全部」);主区按 Agent 数量自适应网格,可同时看多个 Agent;
108
+ - 实时流式输出,推理内容灰显,工具调用渲染成卡片(名称 · 状态 / 参数 / 结果);
109
+ - 总线消息按方向显示:`◀ 发送者`(收到)、`▶ 收件人`(发出)、`指令`(外部);
110
+ - 底部输入框可选「广播」或定向发送;
111
+ - 每个 Agent 生成中会在面板右上角显示「■ 打断」,点击即可打断该 Agent 当前输出(等同 TUI 的 Esc);
112
+ - Markdown 正文用内置轻量渲染(零外部依赖)。
113
+
114
+ 对外接口:
115
+
116
+ - `GET /health` → `{ok, agents, running}`
117
+ - `POST /instruction`,body `{"content": str, "main_agent": str|null}` —— 供外部程序注入指令
118
+ - `WS /ws` —— 事件:`init / message / chunk / turn_end / interrupted / confirm / confirm_cancel / permissions / error`
119
+
120
+ ## 工具确认与权限
121
+
122
+ - `require_confirmation=True` 的工具执行前会弹窗确认(TUI 也支持同类机制)。
123
+ - 全局策略 `tool_confirmation`:`ask`(默认,弹窗)/ `allow`(全放行)/ `deny`(全拒绝)。
124
+ - 弹窗按钮:`允许 / 始终允许 / 拒绝 / 始终拒绝 / 全部允许 / 全部拒绝`。
125
+ - 权限表按 **(Agent, 工具)** 记 `allow` / `deny`,**内存态**(重启即清空)。
126
+ header「权限」窗口可可视化调整,支持「应用到所有 Agent」。
127
+ - 无前端在线时默认拒绝;确认超时(`confirm_timeout`)同样按拒绝处理。
128
+
129
+ ## 边界与注意事项
130
+
131
+ - **软约束**:星型拓扑、禁止广播等,需要写进各 Agent 的 `system_prompt`,框架不强制。
132
+ - **尚无消息深度上限**:Agent 间广播互聊会指数放大(实测一条广播可瞬间产生上千次推理)。
133
+ 建议用提示词约束,或后续加 `Message.depth` 硬边界来兜底。
134
+ - **权限内存态**:跨进程/重启不保留。
135
+ - **事件归属**:`on_stream_chunk`、`on_turn_end` 等由开发者或 Web 层自行挂载,环境本身不管理事件。
136
+ - **思考模型**:`enable_deepseek_reasoning_tools(agent)` 会给 Agent 打 `_reasoning_required` 标记,
137
+ 环境据此给注入的同伴消息补 `reasoning_content`,避免 DeepSeek 思考模式报 400。
138
+
139
+ ## 示例
140
+
141
+ 最小用法可直接参考上面的「快速开始」。更完整的示例(5 个 Agent 的演示、星型 QA 集群等)
142
+ 放在仓库的忽略目录 `little_toy/` 下,**不随 `tina-python` 包发布**。
143
+
144
+ ## 相关集成(可选)
145
+
146
+ - **opencode**:环境侧工具 `ask_opencode` 通过 opencode server 的**会话 API** 向 opencode 发消息;
147
+ opencode 侧可放自定义工具(`.opencode/tools/ask_qa.ts`)调用本服务的 `POST /instruction` 回投指令。
148
+ - **飞书 / Lark**:Agent → 飞书走官方 MCP(`@larksuiteoapi/lark-mcp`);
149
+ 飞书 → Agent 需要机器人事件订阅(建议用长连接 SDK)转发到 `POST /instruction`。
@@ -0,0 +1,43 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "tina-multi-agent"
7
+ version = "0.1.0"
8
+ description = "tina 的实验性多 Agent 场景(消息总线 + Web 调试控制台)"
9
+ readme = { file = "README.md", content-type = "text/markdown" }
10
+ requires-python = ">=3.10"
11
+ license = { text = "Apache Software License" }
12
+ authors = [
13
+ { name = "王出日", email = "wangchuri@163.com" }
14
+ ]
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "License :: OSI Approved :: Apache Software License",
18
+ "Operating System :: OS Independent",
19
+ ]
20
+ dependencies = [
21
+ "tina-python>=0.7.0",
22
+ "fastapi>=0.110",
23
+ "uvicorn>=0.29",
24
+ "websockets>=12",
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://gitee.com/wang-churi/tina"
29
+ Repository = "https://gitee.com/wang-churi/tina.git"
30
+ GitHub = "https://github.com/XIMOCY/tina.git"
31
+
32
+ [project.optional-dependencies]
33
+ test = [
34
+ "pytest>=9.0",
35
+ "pytest-asyncio>=1.4",
36
+ ]
37
+
38
+ [tool.setuptools.packages.find]
39
+ where = ["."]
40
+ include = ["tina_multi_agent*"]
41
+
42
+ [tool.setuptools.package-data]
43
+ tina_multi_agent = ["py.typed", "web/static/*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,13 @@
1
+ """tina 实验性多 Agent 场景。使用方式见包的 README.md。"""
2
+
3
+ from .environment import MultiAgentEnvironment
4
+ from .message import Message
5
+ from .message_bus import MessageBus
6
+ from .web import MultiAgentWeb
7
+
8
+ __all__ = [
9
+ "Message",
10
+ "MessageBus",
11
+ "MultiAgentEnvironment",
12
+ "MultiAgentWeb",
13
+ ]