Skip to main content

企业级 Agent Runtime SDK — 让 AI 工程师专注 Agent 能力开发,无需关心底层基础设施

Project description

wisruntime — 企业级 Agent Runtime SDK

版本: v0.1.0 (MVP) | 日期: 2026-07 | 团队: WIS Team


一、项目概述

1.1 定位

wisruntime 是一个企业级 Agent Runtime SDK(Python),以 pip install 方式提供给 AI 应用工程师使用。

它的核心使命:让 Agent 工程师专注 Agent 能力开发,无需关心底层基础设施。

1.2 一句话描述

为 Agent 开发者提供轻量、可扩展、多框架适配的统一运行时 SDK——用框架原生 API 构建 Agent 后,数行代码即可获得完整的生产级服务端点,并自动接入 WIS Hub 平台能力(MCP / Skill / Sandbox)。

1.3 核心价值

              没有 wisruntime                          有了 wisruntime
              ══════════════                          ══════════════

  AI 工程师 → 写 FastAPI 路由               AI 工程师 → 写 invoke_agent 函数
       → 处理 SSE 流式协议                        → create_server(invoke_agent).start(8000)
       → 对接 MCP 协议                            → ✅ Dify SSE 服务就绪
       → 对接 Skill API                           → ✅ 平台能力自动接入
       → 管理 Sandbox                             → ✅ API-KEY 统一鉴权
       → 对接鉴权系统                             → ✅ 开箱即用
       → 每个应用都重复一遍

1.4 对标参考

本架构深度借鉴了阿里云 AgentRun Python SDK 的分层设计思想,在其基础上针对 WIS Hub 平台的差异化特点(统一 API-KEY 鉴权、Dify SSE 协议、DeepAgents 框架、平台能力托管)进行了重新设计。


二、整体架构

2.1 分层架构图

┌──────────────────────────────────────────────────────────────────────┐
│                        WIS Hub 平台 (AI 中台)                         │
│                                                                      │
│  MCP 服务   │  Skill 服务  │  Sandbox 服务  │  Checkpoint 服务       │
│  (REST)     │  (REST)      │  (REST)        │  (REST)               │
│                                                                      │
│  统一 API-KEY 鉴权:  创建应用 → 勾选能力 → 生成 Key                     │
└────────────────────────────┬─────────────────────────────────────────┘
                             │  HTTPS + Bearer <API-KEY>
                             │
┌────────────────────────────┴─────────────────────────────────────────┐
│                         wisruntime SDK                                │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐  │
│  │  Infrastructure 层                                              │  │
│  │  Config (API-KEY / 端点 / 超时)                                  │  │
│  │  CredentialContext (contextvars: 请求级 API-KEY 注入)            │  │
│  │  BaseModel / 异常定义 / 日志                                     │  │
│  └────────────────────────────────────────────────────────────────┘  │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐  │
│  │  Platform Client 层 (框架无关,只写一次)                         │  │
│  │                                                                  │  │
│  │  mcp/MCPClient      skill/SkillClient                           │  │
│  │  sandbox/SandboxClient   memory/CheckpointClient                │  │
│  │                                                                  │  │
│  │  每个 Client: 自动读 API-KEY, 统一错误处理, 异步 HTTP (httpx)    │  │
│  └────────────────────────────────────────────────────────────────┘  │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐  │
│  │  Capability Bridge 层 (每个框架一份)                             │  │
│  │                                                                  │  │
│  │  adapters/deepagents/                                           │  │
│  │    ├── mcp.py       MCPClient   → DeepAgents BaseTool           │  │
│  │    ├── skill.py     SkillClient → DeepAgents BaseTool           │  │
│  │    └── sandbox.py   SandboxClient → DeepAgents BaseTool          │  │
│  │                                                                  │  │
│  │  adapters/agentscope/  (未来)                                    │  │
│  └────────────────────────────────────────────────────────────────┘  │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐  │
│  │  Adapter 层 (用户可选工具: Agent 对象 → invoke_agent 函数)       │  │
│  │                                                                  │  │
│  │  提供两种使用方式:                                                 │  │
│  │  ① wrap_agent(agent) → invoke_agent 函数 (便捷包装)              │  │
│  │  ② 用户在 invoke_agent 内部手动做事件转换                         │  │
│  │                                                                  │  │
│  │  adapters/deepagents/   (DeepAgents 事件 → CanonicalEvent)      │  │
│  │  adapters/agentscope/   (未来)                                   │  │
│  └────────────────────────────────────────────────────────────────┘  │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐  │
│  │  Server 层 (框架无关,只认函数)                                    │  │
│  │                                                                  │  │
│  │  ┌──────────────┐  ┌──────────────┐  ┌───────────────────┐     │  │
│  │  │ DifyHandler  │  │AGUIHandler   │  │  AgentInvoker     │     │  │
│  │  │ SSE+Blocking │  │  (规划中)     │  │  函数归一化引擎    │     │  │
│  │  └──────┬───────┘  └──────┬───────┘  └─────────┬─────────┘     │  │
│  │         └─────────────────┴────────────────────┘                │  │
│  │                           │                                      │  │
│  │                    CanonicalEvent                                │  │
│  │                    ProtocolRegistry                              │  │
│  └────────────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────────┘

2.2 分层职责

职责 关键组件
Infrastructure 全局配置、凭证注入、基础模型 Config, CredentialContext, BaseModel
Platform Client 封装 WIS Hub REST API 调用,统一鉴权 MCPClient, SkillClient, SandboxClient, CheckpointClient
Capability Bridge 平台客户端 → 框架原生 Tool 对象转换 DeepAgentsMCPTool, DeepAgentsSkillTool
Adapter (用户可选) Agent 对象 → invoke_agent 函数包装,及框架事件 → CanonicalEvent 转换 wrap_agent(), DeepAgentsAdapter
Server HTTP 服务承载、协议路由、请求校验、响应序列化。只接收 invoke_agent 函数 DifyHandler, AgentInvoker, ProtocolRegistry

2.3 关键设计决策

决策 说明 参考来源
API-KEY 唯一鉴权 不引入 AK/SK/STS 签名体系,整个应用只用一个 API-KEY WIS Hub 平台特征
SDK 不管理资源生命周期 资源由 WIS Hub 平台管理,SDK 只做运行时调用(零 CRUD) 与 AgentRun 的核心差异
Platform Client 框架无关 MCP/Skill/Sandbox 客户端只写一次,所有框架共享 AgentRun Resource 层思想
Capability Bridge 每个框架一份 将平台客户端转为框架原生 Tool 对象 AgentRun Integration 层思想
CanonicalEvent 11 种类型 综合 LangChain v2/v3、Dify/Wisknow、AgentRun 四套事件体系 见第三节
Server 只接收 invoke_agent 函数 Server 不知道框架的存在,用户函数 = 唯一入口。与 AgentRun 完全一致 AgentRun AgentRunServer
AgentInvoker 单层归一化 用户函数 yield 的 str/AgentEvent → CanonicalEvent 流 AgentRun AgentInvoker 模式
协议处理器双向负责 Handler 负责请求解析 + 响应序列化 AgentRun Protocol Handler 模式
contextvars 注入 API-KEY Server 模式下从请求 Bearer 头提取 → 注入请求上下文 AgentRun CredentialContext 模式

三、CanonicalEvent 设计

CanonicalEvent 是 wisruntime 的核心抽象——框架事件和协议事件之间唯一的稳定契约。所有 Adapter 产出 CanonicalEvent,所有 ProtocolHandler 消费 CanonicalEvent。

3.1 设计来源

综合分析了四套事件体系,取各自最佳实践:

事件体系 来源 特点
LangChain v2 astream_events(version="v2") Runnable 层级事件,on_*_start/stream/end 模式,支持自定义事件
LangChain v3 astream_events(version="v3") Content-block 协议层级,message-start → block-delta → message-finish,推理/文本/工具调用独立块
Dify / Wisknow event/ 目录中的实体定义 SSE 协议事件,agent_messageagent_thoughtmessage_endsubagent_start/end
AgentRun server/model.py 中的 EventType TEXTREASONINGTOOL_CALLTOOL_CALL_CHUNKTOOL_RESULTERRORCUSTOM

3.2 11 种 CanonicalEvent 类型

┌──────────────────────────────────────────────────────────────────────┐
│                      CanonicalEvent 类型体系                           │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  内容流事件                                                     │   │
│  │                                                                  │   │
│  │  TextDelta         文本增量                                      │   │
│  │    ← v2 on_chat_model_stream(chunk.content)                     │   │
│  │    ← v3 content-block-delta(text-delta)                         │   │
│  │    ← Dify agent_message / text_chunk                            │   │
│  │    ← AgentRun TEXT                                              │   │
│  │                                                                  │   │
│  │  ReasoningDelta    推理增量 (CoT 思维链)                          │   │
│  │    ← v2 additional_kwargs.reasoning_content                     │   │
│  │    ← v3 content-block-delta(reasoning-delta)                    │   │
│  │    ← Dify reasoning_chunk                                       │   │
│  │    ← AgentRun REASONING                                         │   │
│  │                                                                  │   │
│  │  FileOutput        文件输出 (图片/音频/视频/文件)                  │   │
│  │    ← v3 image/audio/video/file content blocks                   │   │
│  │    ← Dify message_file                                          │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  工具调用生命周期 (借鉴 LangChain v3 的 block 模型)              │   │
│  │                                                                  │   │
│  │  ToolCallStart     工具调用开始                                   │   │
│  │    ← v2 on_tool_start (data.input)                              │   │
│  │    ← v3 content-block-start(type=tool_call)                     │   │
│  │    ← Dify agent_thought (tool + tool_input 前半)                │   │
│  │    ← AgentRun TOOL_CALL / TOOL_CALL_CHUNK                       │   │
│  │    data: { id, name, args_delta }  (args 分块流式到达)           │   │
│  │                                                                  │   │
│  │  ToolCallEnd       工具调用结束 (含执行结果)                       │   │
│  │    ← v2 on_tool_end (data.output)                               │   │
│  │    ← v3 content-block-finish(type=tool_call)                    │   │
│  │    ← Dify agent_thought (observation 后半)                      │   │
│  │    ← AgentRun TOOL_RESULT                                       │   │
│  │    data: { id, result, error? }                                 │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  子Agent生命周期 (灵知/Wisknow 自定义场景)                        │   │
│  │                                                                  │   │
│  │  SubAgentStart     子Agent开始运行                                 │   │
│  │    ← 灵知 subagent_start                                        │   │
│  │    data: { agent_name, run_id, task_description }                │   │
│  │                                                                  │   │
│  │  SubAgentEnd       子Agent运行结束                                 │   │
│  │    ← 灵知 subagent_end                                          │   │
│  │    data: { agent_name, run_id, status }                          │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  元事件                                                         │   │
│  │                                                                  │   │
│  │  Usage             Token 用量统计                                 │   │
│  │    ← v2 usage_metadata (on_chat_model_end)                      │   │
│  │    ← v3 message-finish.usage                                    │   │
│  │    ← Dify metadata.usage                                        │   │
│  │    data: { prompt_tokens, completion_tokens, total_tokens }     │   │
│  │                                                                  │   │
│  │  Error             错误事件                                       │   │
│  │    ← 所有体系都有                                                │   │
│  │    data: { message, code?, recoverable? }                       │   │
│  │                                                                  │   │
│  │  Custom            自定义事件 (扩展通道)                           │   │
│  │    ← v2 on_custom_event                                         │   │
│  │    ← 灵知 todo_update / recommendation_card / next_step         │   │
│  │    data: { name, payload }                                      │   │
│  │                                                                  │   │
│  │  Done              流结束标记                                     │   │
│  │    ← v3 message-finish                                          │   │
│  │    ← Dify message_end                                           │   │
│  │    ← AgentRun 流自然结束 (隐式)                                   │   │
│  │    data: { metadata? }                                          │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

3.3 数据流

                    ┌─── invoke_agent 函数 (用户编写) ───┐
                    │                                    │
                    │  用户可以在函数内部:                  │
                    │  · 直接 yield str / CanonicalEvent  │
                    │  · 使用框架 Agent + Adapter 转换     │
                    │  · 调用 MCPClient / SkillClient     │
                    │                                    │
                    └────────────┬───────────────────────┘
                                 │
                                 ▼
                    ┌─────────────────────────┐
                    │     AgentInvoker         │  ← 归一化: str → TextDelta
                    │                          │           异常 → Error
                    │  AsyncGenerator[          │           透传 CanonicalEvent
                    │    CanonicalEvent]        │
                    └────────────┬────────────┘
                                 │
                                 ▼
                    ┌─────────────────────────┐
                    │   ProtocolHandler        │  ← 序列化: CanonicalEvent → SSE/JSON
                    │                          │
                    │  DifyHandler → Dify SSE  │
                    │  AGUIHandler → AG-UI     │
                    └─────────────────────────┘

  Adapter 层 (用户可选工具): 框架 Agent + Adapter → CanonicalEvent 流 → 在 invoke_agent 中 yield

四、分层详解

4.1 Infrastructure 层

┌────────────────────────────────────────────────────┐
│  Config                                             │
│  ├── api_key: str          统一 API-KEY             │
│  ├── hub_endpoint: str     WIS Hub 地址             │
│  ├── timeout: int = 600    请求超时(秒)             │
│  └── 获取优先级:                                     │
│      1. 显式传入 Config(api_key="...")              │
│      2. 环境变量 WIS_HUB_API_KEY                    │
│      3. 请求级 contextvars overlay (Server 模式)     │
│                                                     │
│  CredentialContext (contextvars)                    │
│  ├── get_request_api_key() → Optional[str]          │
│  ├── set_request_api_key(key) 上下文管理器          │
│  └── 用途: Server 模式从 Bearer 头注入 → 全局可用    │
│                                                     │
│  ApiKeyMiddleware (纯 ASGI)                          │
│  ├── 每次请求从 Authorization: Bearer <KEY> 解析     │
│  ├── 注入 contextvars overlay                       │
│  └── 请求结束时自动复位                               │
└────────────────────────────────────────────────────┘

与 AgentRun 的差异: AgentRun 使用 AK/SK + STS + RAM 签名三级体系,wisruntime 只使用 API-KEY,结构大幅简化。但 contextvars 注入模式完全复用。

4.2 Platform Client 层

核心原则: 框架无关,只写一次。只做运行时调用,不做资源 CRUD。

WIS Hub 平台负责资源的创建和管理,SDK 不需要 create() / delete() 操作。每个 Client 只需要:

# 统一模式 (以 MCP 为例)
class MCPClient:
    def __init__(self, base_url=None, api_key=None, timeout=600):
        self._base_url = base_url or f"{Config.current().hub_endpoint}/mcp"
        self._api_key = api_key
        self._timeout = timeout

    @property
    def api_key(self) -> str:
        """三级获取: 显式传入 → contextvars → 环境变量"""
        return self._api_key or CredentialContext.get_request_api_key()

    async def call(self, method: str, params: dict) -> dict:
        """调用 MCP 工具"""
        ...

    async def list_tools(self) -> list[dict]:
        """列出可用工具"""
        ...

各 Client 职责:

Client 职责 端点示例
MCPClient 调用 WIS Hub 托管的 MCP 服务 POST /mcp/invoke
SkillClient 调用 WIS Hub 托管的 Skill POST /skill/{name}/invoke
SandboxClient 代码/浏览器沙箱执行 POST /sandbox/execute
CheckpointClient 会话检查点读写 GET/POST /checkpoint/{conversation_id}

4.3 Capability Bridge 层

核心原则: 将平台客户端转换为框架原生的 Tool 对象。每个框架写一份。

# 以 DeepAgents 为例
from wisruntime.adapters.deepagents.mcp import DeepAgentsMCPTool

# MCPClient → DeepAgents BaseTool
tool = DeepAgentsMCPTool(
    client=MCPClient(),
    name="company_search",
    description="搜索公司内部知识库"
)

agent = create_deep_agent(tools=[tool])

为什么需要这一层? DeepAgents 的 BaseTool 有特定的接口要求(如 ainvokeschemaname)。MCPClient 返回的是原始 HTTP 响应。这层 Bridge 负责把 REST API 调用适配为框架期望的 Tool 协议。

4.4 Adapter 层

定位: 用户可选工具层。Server 不调用 Adapter,Adapter 是用户在 invoke_agent 中使用的辅助工具。

与 AgentRun 的设计一致:AgentRun 的 AgentRunConverter(仅 LangGraph 需要)是用户在 invoke_agent 内部自行使用的,不是 Server 的依赖。

两种使用方式:

方式 A: 用 wrap_agent 把 Agent 对象包装成 invoke_agent 函数 (便捷)
════════════════════════════════════════════════════════════════════

  from wisruntime.adapters.deepagents import wrap_agent

  agent = create_deep_agent(tools=[...])
  create_server(wrap_agent(agent)).start(8000)
  # wrap_agent 内部: Agent.astream_events → CanonicalEvent 流 → invoke_agent 函数


方式 B: 在 invoke_agent 内部手动做事件转换 (完全控制)
════════════════════════════════════════════════════════════════════

  from wisruntime.adapters.deepagents import DeepAgentsAdapter

  async def my_invoke_agent(request: AgentRequest):
      agent = create_deep_agent(tools=[...])
      adapter = DeepAgentsAdapter()
      async for event in agent.astream_events(request.messages):
          canonical = adapter.convert(event)  # 框架事件 → CanonicalEvent
          if canonical:
              yield canonical

  create_server(my_invoke_agent).start(8000)

Adapter 内部需要处理的核心问题 (参考 AgentRun AgentRunConverter):

问题 解决方案
流式工具调用 ID 追踪 维护 tool_call_index → id 映射,ToolCallStart 时携带 id
推理/文本分离 检测 reasoning_contentreasoning-deltaReasoningDelta
结束检测 v2: on_chain_end + name="LangGraph"; v3: message-finish
错误降级 on_tool_errorToolCallEnd(error=...),不升级为全局 Error

4.5 Server 层

核心原则: 与 AgentRun 完全一致——只接收 invoke_agent 函数,不感知框架。

┌──────────────────────────────────────────────────────────────┐
│  WisRuntimeServer                                             │
│                                                              │
│  构造: create_server(invoke_agent, protocols=[DifyHandler()]) │
│                                                              │
│  初始化流程:                                                   │
│   1. 创建 FastAPI app                                         │
│   2. 注入 ApiKeyMiddleware → contextvars                      │
│   3. (可选) checkpoint 自动持久化包装                          │
│   4. 创建 AgentInvoker(invoke_agent)                          │
│   5. 注册 /health 路由                                        │
│   6. 挂载 ProtocolHandler 路由                                 │
│                                                              │
│  两种使用模式:                                                 │
│                                                              │
│  模式 1: 独立服务 (开发/调试)                                   │
│    create_server(invoke_agent).start(port=8000)               │
│                                                              │
│  模式 2: FastAPI 子应用 (生产推荐)                              │
│    app.mount("/agent", create_server(invoke_agent).as_fastapi_app())│
└──────────────────────────────────────────────────────────────┘

AgentInvoker — 唯一的归一化入口

invoke_agent 函数 → AgentInvoker.invoke(fn, request) → CanonicalEvent 流

  自动检测:
  ├── async generator  → 直接迭代
  ├── async function   → await 得到返回值,单次 yield
  ├── sync function    → loop.run_in_executor(线程池) + contextvars 传播
  ├── str              → CanonicalEvent(type=TextDelta, data={delta: str})
  ├── CanonicalEvent   → 透传
  ├── None             → 跳过
  └── Exception        → CanonicalEvent(type=Error, ...)

  设计决策:
  ├── Done 事件: AgentInvoker 在 generator 耗尽时自动插入
  │     (Dify 协议必须有 message_end,AgentRun 不需要)
  ├── str 语义: 用户 yield 的 str 就是模型的文本输出 → TextDelta
  │     高级类型 (Reasoning/ToolCall) 用户通过直接 yield CanonicalEvent 表达
  └── 函数签名: 不强约束,运行时 inspect 检测 (与 AgentRun 一致)
      用户函数接收 AgentRequest 作为第一个位置参数

AgentRequest — 归一化请求模型

class Message(BaseModel):
    role: Literal["system", "user", "assistant", "tool"]
    content: str | list[dict]    # 文本或多模态
    name: str | None = None

class AgentRequest(BaseModel):
    messages: list[Message]            # 归一化消息列表
    stream: bool = True                # 是否流式
    conversation_id: str | None = None # 会话ID
    user_id: str | None = None         # 用户ID
    headers: dict[str, str]            # 关键 header 副本 (可跨线程)
    raw_request: Request | None = None # 原始 Starlette Request (本地可用)
    protocol_extensions: dict = {}     # 协议特有字段 (如 Dify 的 inputs/files)

ProtocolHandler — 响应序列化

┌─────────────────────────────────────────────────────────┐
│  DifyHandler                                              │
│                                                          │
│  端点:                                                    │
│    POST /dify/v1/chat-messages    SSE Streaming          │
│    POST /dify/v1/chat-messages    Blocking (stream=false) │
│    POST /dify/v1/chat-messages/{task_id}/stop (Phase 3)  │
│                                                          │
│  CanonicalEvent → Dify SSE 映射:                           │
│    TextDelta      → agent_message (answer=delta)         │
│    ReasoningDelta → reasoning_chunk (reasoning=delta)    │
│    ToolCallStart  → agent_thought (tool, tool_input)    │
│    ToolCallEnd    → agent_thought (observation)          │
│    SubAgentStart  → subagent_start                      │
│    SubAgentEnd    → subagent_end                        │
│    FileOutput     → message_file                        │
│    Usage          → (累积到 message_end.metadata.usage)   │
│    Error          → error (message, code, status)        │
│    Custom         → {event: name, ...payload}           │
│    Done           → message_end                         │
│                                                          │
│  DifyHandler 内部维护的协议特有状态:                        │
│  ├── agent_thought 的 id (唯一标识) + position (递增)     │
│  │     CanonicalEvent 不携带 Dify 特定的 id/position,    │
│  │     由 Handler 自行生成,保持 CanonicalEvent 协议无关   │
│  └── 心跳: 每 10 秒自动发送 data: {"event": "ping"}\n\n  │
│        (asyncio background task)                         │
│                                                          │
│  AGUIHandler (规划中)                                      │
│    CanonicalEvent → AG-UI SSE 格式                        │
└─────────────────────────────────────────────────────────┘

WisRuntimeServer — 组装

class ServerConfig(BaseModel):
    cors_origins: list[str] = ["*"]
    health_path: str = "/health"

class WisRuntimeServer:
    def __init__(self, invoker: AgentInvoker, protocols: list[ProtocolHandler], config: ServerConfig):
        # 1. 创建 FastAPI app
        # 2. (Phase 2) 注入 ApiKeyMiddleware
        # 3. for handler in protocols: handler.install(app, invoker)
        # 4. 注册 health 路由
        # 5. 配置 CORS

    def start(self, host="0.0.0.0", port=8000):
        """模式 1: 独立服务 (内部调 uvicorn.run)"""

    def as_fastapi_app(self) -> FastAPI:
        """模式 2: 导出为 FastAPI 子应用,供 app.mount()"""

    # 模式 3 (as_router) 不做。用户如需 include_router 级别的控制,
    # 可以手动创建 AgentInvoker + DifyHandler 自行组装。

def create_server(
    invoke_agent: Callable,
    *,
    protocols: list[ProtocolHandler] | None = None,  # 默认 [DifyHandler()]
    config: ServerConfig | None = None,
    checkpoint_enabled: bool = False,                 # Phase 3
) -> WisRuntimeServer:
    ...

五、用户故事与实施蓝图

5.1 用户故事总览

故事 1 ──────────────────────────────────────────────────────────────
│  用户故事: 作为 AI 工程师,我只需写一个 invoke_agent 函数,              │
│           就能获得一个 Dify 兼容的 SSE 服务端点                       │
│                                                                   │
│  验收标准:                                                          │
│    from wisruntime import create_server                             │
│    from wisruntime.model import AgentRequest                        │
│                                                                   │
│    async def my_invoke_agent(request: AgentRequest):                 │
│        # 用户可以自由使用任何框架、任意逻辑                            │
│        async for chunk in llm.astream(request.messages):             │
│            yield chunk.content   # yield str 即可                    │
│                                                                   │
│    create_server(my_invoke_agent).start(port=8000)                   │
│    # → curl -X POST http://localhost:8000/dify/v1/chat-messages     │
│    #       -d '{"query": "你好", "response_mode": "streaming"}'      │
│    # → SSE 流式响应,包含 agent_message / agent_thought / message_end│
└─────────────────────────────────────────────────────────────────────┘

故事 2 ──────────────────────────────────────────────────────────────
│  用户故事: 作为 AI 工程师,我接入 WIS Hub MCP 服务时,                  │
│           只需创建一个 MCPClient,它能自动处理鉴权和协议转换             │
│                                                                   │
│  验收标准:                                                          │
│    from wisruntime.mcp import MCPClient                             │
│    from wisruntime.adapters.deepagents.mcp import DeepAgentsMCPTool  │
│    from wisruntime.adapters.deepagents import wrap_agent             │
│    from deepagents import create_deep_agent                          │
│                                                                   │
│    client = MCPClient()           # 自动读 WIS_HUB_API_KEY          │
│    tool = DeepAgentsMCPTool(client, name="search")                   │
│    agent = create_deep_agent(tools=[tool])                            │
│    create_server(wrap_agent(agent)).start(8000)                       │
│    # → Agent 调用工具时,MCPClient 自动携带 Bearer 头请求 WIS Hub     │
└─────────────────────────────────────────────────────────────────────┘

故事 3 ──────────────────────────────────────────────────────────────
│  用户故事: 作为 AI 工程师,我可以将 wisruntime 服务嵌入到已有            │
│           FastAPI 应用中,作为子路由挂载                               │
│                                                                   │
│  验收标准:                                                          │
│    from fastapi import FastAPI                                      │
│    app = FastAPI()                                                  │
│    app.mount("/agent", create_server(my_invoke_agent).as_fastapi_app())│
│    # → /agent/dify/v1/chat-messages 就绪                            │
│    # → 复用主应用的 middleware 和 lifecycle                          │
└─────────────────────────────────────────────────────────────────────┘

故事 4 ──────────────────────────────────────────────────────────────
│  用户故事: 作为 AI 工程师,我用 wrap_agent 包装 deepagents Agent,      │
│           一行代码就生成 invoke_agent 函数                             │
│                                                                   │
│  验收标准:                                                          │
│    from deepagents import create_deep_agent                          │
│    from wisruntime.adapters.deepagents import wrap_agent             │
│                                                                   │
│    agent = create_deep_agent(tools=[...])                             │
│    create_server(wrap_agent(agent)).start(8000)                       │
│    # → wrap_agent 内部: astream_events → CanonicalEvent → yield      │
└─────────────────────────────────────────────────────────────────────┘

故事 5 ──────────────────────────────────────────────────────────────
│  用户故事: 作为 AI 工程师,我的 Agent 需要调用 WIS Hub 的 Skill 和       │
│           Sandbox 能力,使用与 MCP 相同的简洁 API                       │
│                                                                   │
│  验收标准:                                                          │
│    from wisruntime.skill import SkillClient                          │
│    from wisruntime.sandbox import SandboxClient                       │
│    from wisruntime.adapters.deepagents.skill import DeepAgentsSkillTool│
│    from wisruntime.adapters.deepagents.sandbox import DeepAgentsSandboxTool│
│    agent = create_deep_agent(tools=[                                   │
│        DeepAgentsSkillTool(SkillClient(), name="data_analysis"),       │
│        DeepAgentsSandboxTool(SandboxClient(), name="code_executor"),   │
│    ])                                                                  │
│    create_server(wrap_agent(agent)).start(8000)                        │
└─────────────────────────────────────────────────────────────────────┘

故事 6 ──────────────────────────────────────────────────────────────
│  用户故事: 作为 AI 工程师,我的 Agent 对话历史可以自动持久化到           │
│           WIS Hub Checkpoint 服务,支持断点续传                         │
│                                                                   │
│  验收标准:                                                          │
│    create_server(my_invoke_agent, checkpoint_enabled=True).start(8000) │
│    # → 每次对话自动保存到 WIS Hub                                      │
│    # → 下次请求带有相同 conversation_id 时恢复上下文                    │
└─────────────────────────────────────────────────────────────────────┘

5.2 实施阶段

Phase 0: 项目骨架 (已完成)
══════════════════════════
  ✅ 清理旧代码,确定新的架构方向
  ✅ 分析 AgentRun、LangChain、Dify 参考架构
  ✅ 确定 CanonicalEvent 11 种类型
  ✅ 确定分层架构

Phase 1: 核心基础设施 + MVP Server (当前)
════════════════════════════════════
  目标: 用户故事 1 — 写 invoke_agent 函数,获得 Dify SSE 端点

  范围内:
  □ CanonicalEvent 11 种类型定义
  □ AgentRequest + Message 模型
  □ Config + CredentialContext (contextvars 定义) — ApiKeyMiddleware 后置到 Phase 2
  □ AgentInvoker (async/sync/iterator 检测, str→TextDelta, Exception→Error, 自动 Done)
  □ DifyHandler (parse_request + _format_stream + 心跳)
      - agent_thought 的 id/position 由 Handler 内部维护
      - Blocking 模式: 收集全部事件 → JSONResponse
  □ WisRuntimeServer (start + as_fastapi_app) — as_router 不做
  □ ProtocolRegistry + create_server 顶层 API
  □ 单元测试 + SSE 端到端对接测试

  范围外 (后续故事):
  ✗ ApiKeyMiddleware (Phase 2, 配合 MCPClient)
  ✗ DeepAgentsAdapter / wrap_agent (Phase 3)
  ✗ AGUIHandler (Phase 4)
  ✗ Checkpoint 自动持久化 (Phase 3)
  ✗ Stop endpoint (Phase 3)
  ✗ Platform Client 层 (Phase 2)

Phase 2: 平台能力接入
══════════════════
  目标: 用户故事 2 + 5 — MCP/Skill/Sandbox 接入

  □ MCPClient + MCP 数据模型
  □ SkillClient + Skill 数据模型
  □ SandboxClient + Sandbox 数据模型
  □ DeepAgentsMCPTool (MCPClient → BaseTool)
  □ DeepAgentsSkillTool (SkillClient → BaseTool)
  □ DeepAgentsSandboxTool (SandboxClient → BaseTool)

Phase 3: Adapter + 高级特性
══════════════════════════
  目标: 用户故事 3 + 4 + 6 — wrap_agent、FastAPI 嵌入、Checkpoint

  □ DeepAgentsAdapter (astream_events → CanonicalEvent 转换)
  □ wrap_agent(agent) 工厂函数
  □ CheckpointClient + 自动持久化包装
  □ SubAgentStart/End 支持
  □ Custom 事件 (todo, recommendation_card, next_step)
  □ 错误恢复与 graceful shutdown
  □ Stop endpoint (对话中断)

Phase 4: 多框架 + 多协议
══════════════════════
  目标: 验证可扩展性

  □ AgentScope Adapter
  □ AGUI Handler
  □ 内部 PyPI 发布
  □ 性能基准测试

5.3 目录结构 (目标态)

wisruntime/
├── __init__.py                  # 顶层导出: create_server, Config
├── config.py                    # Config, CredentialContext
├── middleware.py                # ApiKeyMiddleware (纯 ASGI)
├── model.py                     # CanonicalEvent, AgentRequest 等核心模型
├── exceptions.py                # 自定义异常
│
├── mcp/                         # Platform Client: MCP
│   ├── __init__.py
│   ├── client.py                #   MCPClient
│   └── model.py                 #   MCP 请求/响应模型
│
├── skill/                       # Platform Client: Skill
│   ├── __init__.py
│   ├── client.py                #   SkillClient
│   └── model.py
│
├── sandbox/                     # Platform Client: Sandbox
│   ├── __init__.py
│   ├── client.py                #   SandboxClient
│   └── model.py
│
├── memory/                      # Platform Client: Checkpoint
│   ├── __init__.py
│   ├── client.py                #   CheckpointClient
│   └── model.py
│
├── adapters/                    # Adapter + Capability Bridge (用户可选工具)
│   ├── __init__.py              #   导出 wrap_agent 等便捷函数
│   ├── base.py                  #   框架事件 → CanonicalEvent 转换基类
│   └── deepagents/              #   DeepAgents 框架
│       ├── __init__.py          #     导出 wrap_agent, DeepAgentsAdapter
│       ├── adapter.py           #     DeepAgentsAdapter (事件转换)
│       ├── mcp.py               #     DeepAgentsMCPTool (Capability Bridge)
│       ├── skill.py             #     DeepAgentsSkillTool
│       └── sandbox.py           #     DeepAgentsSandboxTool
│
├── server/                      # Server 层
│   ├── __init__.py
│   ├── server.py                #   WisRuntimeServer (FastAPI 组装)
│   ├── invoker.py               #   AgentInvoker (函数归一化)
│   ├── model.py                 #   AgentRequest, ProtocolRegistry
│   ├── dify_handler.py          #   DifyHandler (SSE + Blocking)
│   └── agui_handler.py          #   AGUIHandler (规划中)
│
└── integration/                 # 会话持久化 + 框架 Memory 适配
    ├── __init__.py
    └── deepagents/
        └── memory.py            #   WISCheckpointMemory (CheckpointClient → DeepAgents Memory)

六、技术规格

6.1 运行时依赖

版本 用途
fastapi ≥ 0.110 Web 框架
uvicorn[standard] ≥ 0.27 ASGI 服务器
sse-starlette ≥ 2.0 SSE 流式响应
pydantic ≥ 2.0 数据校验与序列化
httpx ≥ 0.27 异步 HTTP 客户端

6.2 环境变量

变量 用途 必填
WIS_HUB_API_KEY WIS Hub 统一 API-KEY 使用 MCP/Skill/Sandbox/Checkpoint 时必填
WIS_HUB_ENDPOINT WIS Hub 地址 可选,默认读取 SDK 内置配置

6.3 Python 版本

≥ 3.11


七、参考资源

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wisruntime-0.1.0.tar.gz (47.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wisruntime-0.1.0-py3-none-any.whl (30.0 kB view details)

Uploaded Python 3

File details

Details for the file wisruntime-0.1.0.tar.gz.

File metadata

  • Download URL: wisruntime-0.1.0.tar.gz
  • Upload date:
  • Size: 47.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for wisruntime-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3bd4ddef65c4d2318997bde77203eeaf27253eb79b71de5e18121d2ea3d5991f
MD5 f5e27641c10ce0417850a890644705d9
BLAKE2b-256 b75f892be12d76d90e931d4fbd4d1b9189c6edb0ba01823c9264d3b80557decc

See more details on using hashes here.

File details

Details for the file wisruntime-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: wisruntime-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for wisruntime-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d076df3cfc792201e422b43b32687a3839b31671543b3444630953fc094ea9bc
MD5 5b6c96ebd7a4be3b2d93e7f393e9f096
BLAKE2b-256 a87b4d6ae8079b02ffefa8f156e62b57dff4a001c1ffbd5d7b4de22e9ce11abd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page