qi-pi / pi-agent-py v1
Python Agent 微内核:Session Event Log 是唯一事实来源,Everything is a Plugin。
qi-pi v1 不再把 Agent Loop、工具、Provider、持久化或 Server 当作 Core 的固定组成。qi_agent_core
只提供五种原语:ServiceKey、Context、Scope、Effect 和 EventSpec。其余能力均由同进程插件
提供,可独立替换、组合和按 generation 热重载。
这是破坏性 v1:不兼容 API v1 插件,也不读取旧 Session 数据。
架构
flowchart LR
Client["Web / Desktop / Headless"] --> Transport["HTTP/SSE 插件"]
Transport --> Driver["AgentDriver 插件"]
Driver --> Session["SessionService"]
Driver --> Provider["LLMService 插件"]
Driver --> Tools["Tool Pipeline 插件"]
Session --> JSONL["Zstd JSONL Persistence 插件"]
Session --> Projection["可重建 SQLite 投影"]
Core["qi_agent_core 微内核"] --- Driver
Core --- Session
Core --- Provider
Core --- Tools
Plugins["Blog / Memory / Live2D / Voice / Telemetry"] --> Core
核心约束:
Session Event Log是消息历史、回放、Resume、Audit 和 Telemetry 的共同事实源。derive_messages()从事件 surface 投影模型历史,不维护第二份Agent.messages。assistant/chunk保留流式过程,assistant/message保存组装后的权威消息。- Session Stream 保存可恢复事实;Agent Control Stream 只发送活跃状态。
- 活跃 Turn 租用创建时的 generation;热重载只影响新 Turn。
- 工具策略使用单调决策:
abstain < require_approval < deny。 - Parallel 工具只并发执行 body;策略、post、实时通知和持久提交仍保持模型调用顺序。
- Tool Ledger 记录
prepared → dispatched → external-result-recorded → committed,未知副作用不会盲目重试。 - 不序列化协程栈;恢复只从显式事件和检查点重新进入。
安装与启动
Python 3.12+。用户只需管理两个公开 Distribution:qi-ai 与 qi-agent。
uv tool install qi-agent
export DASHSCOPE_API_KEY='...'
qi-agent serve
源码开发:
uv sync --all-packages
uv run pytest
uv run ruff check packages tests
uv run pyright
HTTP 的最小流程:
curl -X POST http://127.0.0.1:8765/api/v1/sessions \
-H 'content-type: application/json' \
-d '{"metadata":{"title":"demo"}}'
curl -X POST http://127.0.0.1:8765/api/v1/turns \
-H 'content-type: application/json' \
-d '{
"session_id":"SESSION_ID",
"prompt":"你好",
"model":{"id":"qwen3-max","provider":"dashscope","display_name":"Qwen3 Max"}
}'
事实流使用 /api/v1/sessions/{session_id}/events?after_sequence=...;活跃控制流使用
/api/v1/turns/{turn_id}/control-events。
产品 Profile 通过稳定 ServiceKey 接入同一个 Transport:live2d Profile 提供受 Manifest
白名单约束的模型资产、Snapshot、Command 和 SSE;启用 voice 后,
POST /api/v1/speech/synthesize 为已存在 Session 返回私有、禁止缓存的 PCM 流。HTTP 层统一执行
Origin、请求体上限、Bearer/Cookie 与 CSRF 策略,产品插件不重复实现认证。
最小插件
from typing import Any
from qi_agent_core import Context, ServiceKey
from qi_agent_runtime import TOOLS, ToolDefinition
class GreetPlugin:
id = "greet"
inject: tuple[ServiceKey[Any], ...] = (TOOLS,)
async def apply(self, ctx: Context) -> None:
tool = ToolDefinition(
name="greet",
description="Greet someone by name.",
parameters={
"type": "object",
"properties": {"name": {"type": "string"}},
"required": ["name"],
},
execute=lambda args, _ctx: f"Hello, {args['name']}!",
)
ctx.effect(ctx.require(TOOLS).register(tool))
ctx.provide()、ctx.on()、ctx.effect() 和服务的 register() 都产生 disposer;插件作用域退出时按
逆序自动释放监听器、后台任务、Provider Client 和连接。
插件不是由 Runtime 的 if/else 装配。PluginCatalog 注册工厂与 Manifest,Bundle → Profile → Patch 选择最终 generation;未指定 Profile 时使用 headless。内置产品 Profile 为 headless、
web、blog 和 live2d。Patch 对对象递归合并、数组整段替换,null 删除字段。
本地/Git/PyPI 插件统一管理:
qi-agent install ./my-plugin
qi-agent install github:owner/my-plugin@v1.0.0
qi-agent install pypi:qi-agent-my-plugin@1.0.0
qi-agent update my-plugin
qi-agent update
qi-agent remove my-plugin
目录插件必须声明 Manifest API 2:
[extension]
id = "greet"
version = "1.0.0"
api_version = "2"
entrypoint = "plugin.py:create_plugin"
requires_agent = ">=1,<2"
provides = []
inject = ["tools"]
replaces = []
同 ID 或同 Service 替换必须通过 replaces 显式声明。Manifest 的服务声明、配置 Schema 与 Agent
版本范围会在候选 generation 装配前校验;失败时完整回滚。
内置插件与数据
| 插件 | 提供能力 |
|---|---|
session-persistence-jsonl |
每 Session append-only Zstandard frame 日志 |
session |
校验、surface、派生消息和事实订阅 |
providers |
Provider Registry |
command-inbox / compaction |
持久输入队列与 surface 替换 |
tools |
Gate、审批、wrapper、执行、render 和结果冻结 |
react-agent-loop |
默认可恢复状态机 |
telemetry-sqlite |
可删除、可重建的管理投影 |
website / blog |
安全网页动作与博客检索 Tool |
memory |
Tool、动态上下文、事件观察和管理动作 |
live2d / voice |
Avatar 与流式语音服务 |
默认 Session 位于新 v1/sessions 数据根。SQLite 只用于列表、搜索、统计等投影,不是模型历史真相
源。v1 不要求 PostgreSQL、Redis、ClickHouse 或 OTel Collector。
工具结果使用 TextContent | ImageContent 富内容块。Anthropic 转换为原生 tool-result 图片块;
Gemini 3 转换为原生 multimodal function response;不支持统一工具图片协议的
OpenAI-compatible endpoint 使用带类型信息的文本降级。
文档入口
正式 Web UI 不在本仓库。前端通过轻量 SDK 回放 Session 事件、按 sequence 去重,并使用稳定
(kind, id) 节点键进行 start/update/end 投影。
Metadata
Release files for qi-agent 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| qi_agent-1.0.0.tar.gz | 305.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qi_agent-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 422.0 kB
Release files / qi_agent-1.0.0.tar.gz
| Download URL | qi_agent-1.0.0.tar.gz |
|---|---|
| Size | 305.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0cb31ba5eea21fd64b7c1d0f8081d91d4cb4d4a52af9616b57189092994f9718
|
|
BLAKE2b-256 checksum How to use checksums |
4f410b7c70d4c0d22523b07495b6296d75dcad9eda47db3e80daaa947ac7f091
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / qi_agent-1.0.0-py3-none-any.whl
| Download URL | qi_agent-1.0.0-py3-none-any.whl |
|---|---|
| Size | 116.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a8facbe5611544f853642eb0a17c7d6eef7cb952998eccd02c04e1e073660297
|
|
BLAKE2b-256 checksum How to use checksums |
9a06af87f73c98054876b9b447fefb31aafb74878f66f1a515a29a725230a9c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|