AS AgentScopeAPI 手册 / API Reference
MODULE C1 · assembler · 120 XP · 25 MIN

装配服务Assemble the service

先说问题The problem

你已经写过 agent,但你从没「运行过它所在的进程」。把 AgentScope 从库升级成服务要过的第一道门是 create_app 的四个必填积木——少一个,一个请求都进不来。

You have written agents; you have never run the process they live in. Promoting AgentScope from library to service starts with the blocks create_app demands. Miss one and not one request gets in.

先动手Do it first

先在页面上接线——页面只懂规则。然后跑下面那条判题,那才是真会失败的东西。Wire it on the page — the bench only knows the rules. Then run the check below; that is the part that can actually fail.

状态存储Persistence storage= StorageBase 必填required

托管 agent、会话、凭据与消息。没有它,进程一重启,服务就没有任何记忆。Owns agents, sessions, credentials and messages. Without it the service has no memory across process restarts.

Empty: the service will not boot空着:服务起不来
消息总线Transport message_bus= MessageBus 必填required

负责跨会话收件箱投递与空闲会话唤醒。它与存储刻意分离,所以传输后端和持久化后端可以是两套不同的系统。Carries cross-session inbox delivery and idle-session triggers. Deliberately separate from storage, so the transport backend can differ from the persistence backend.

Empty: the service will not boot空着:服务起不来
工作区沙箱Execution sandbox workspace_manager= WorkspaceManagerBase 必填required

决定工具到底在哪里执行、隔离到什么粒度。每次 chat 运行和每个 /workspace 接口都依赖它。Decides where a tool actually runs and how isolated it is. Every chat run and every /workspace route depends on it.

Empty: the service will not boot空着:服务起不来
模型凭据Model backends extra_credentials= list[Type[CredentialBase]] 选填optional

注册服务可以解析的模型族。放入脚本化凭据后,整条链路可以离线、确定性地跑通——这正是评测能做真的前提。Registers the model families the service may resolve. A scripted credential makes the whole stack runnable offline and deterministic, which is what makes an evaluation honest.

Empty: fine for now空着:以后再插也行
你拼出来的东西What you assembled
create_app(…)

为什么这样设计Why it is built this way

01先选存储,再谈记忆Pick storage before memory

AsyncSQLAlchemyStorage 吃一条 SQLAlchemy 异步 URL。SQLite 就够本机跑,同一行代码换成 postgresql+asyncpg 就是生产。状态存储决定进程死后还剩什么。

Pick storage before talking about memory. AsyncSQLAlchemyStorage takes any async SQLAlchemy URL: SQLite runs on a laptop, and the same line swapped to postgresql+asyncpg is production. Storage decides what survives the process.

02总线不是存储The bus is not the store

InMemoryMessageBus 让你不用装 Redis 就能跑,代价是跨不了进程:两个副本互相看不见收件箱。框架把传输和持久化刻意分开,就是为了让你能一边存 SQL、一边换 Redis 传输。

The bus is not the store. InMemoryMessageBus runs with no broker installed, at the price of never crossing processes: two replicas cannot see each other's inbox. Transport is deliberately split from persistence so you can keep SQL rows and swap to a Redis transport.

03沙箱只是目录边界A directory is not a security boundary

LocalWorkspaceManager 的隔离是按 agent 分目录,不是安全边界——工具仍然碰得到宿主机。这一块的真正能力在 C7 换掉它时才出现。

LocalWorkspaceManager isolates by directory per agent, which is not a security boundary: a tool can still reach the host. This block's real power only shows up when C7 swaps it.

04凭据决定大脑The credential decides the brain

credential 是 pydantic 模型,它的 get_chat_model_class() 决定服务构造哪个模型。注册一个脚本化凭据,整条链路就能离线、确定性地跑——这是后面评测能做真的前提。

A credential is a pydantic model whose get_chat_model_class() decides which model the service builds. Register a scripted credential and the whole chain runs offline and deterministically — the precondition for an honest evaluation later.

用到的 APIAPIs in play

代码The code

C1 · Python
from agentscope.app import create_app
from agentscope.app.storage import AsyncSQLAlchemyStorage
from agentscope.app.message_bus import InMemoryMessageBus
from agentscope.app.workspace_manager import LocalWorkspaceManager

app = create_app(
    storage=AsyncSQLAlchemyStorage("sqlite+aiosqlite:///./capstone.db"),
    message_bus=InMemoryMessageBus(),
    workspace_manager=LocalWorkspaceManager("./workspaces"),
    extra_credentials=[TapeCredential],
)

判题The check

<span class="ui-zh">运行这条</span><span class="ui-en">Run this</span>
python lab.py run c1

它断言了什么What it asserts

  • POST /credential/ -> 201, id af82d752
  • POST /agent/ -> 201, id d132bbca
  • POST /session/ -> 201, id 0e6b92d9 (the id rotates every run; what is asserted is that all three routes accepted the assembly)
  • one chat turn, then status idle (not running, not awaiting anything)
  • reply read back from persistence
  • all three required slots enforced
  • a transport block in the storage slot is rejected

会踩的坑Where it hurts

  • TestClient(app) 不会跑 lifespan,storage 引擎没打开,第一个请求就 RuntimeError: AsyncSQLAlchemyStorage is not initialised。必须 with TestClient(app) as client。

    TestClient(app) does not run the lifespan, so the storage engine never opens and the first request raises RuntimeError: AsyncSQLAlchemyStorage is not initialised. You need with TestClient(app) as client.

费曼闸门Say it back

为什么 message_bus 不能直接用 storage 代替?说清两者各自的生命周期。

Why can the message bus not just be the storage? Spell out each one's lifecycle.

页面只存通行码的哈希。判题没真跑过,这里就解不开。The page stores a hash, not the code. Nothing unlocks until the command really ran.

基于官方固定版本源码静态生成Generated from pinned official sources · Python 2.0.11 · Java 2.0.4
签名与文档为静态抽取;如有疑问请以源码为准。Signatures and docs are extracted statically; verify against the source when in doubt.