Skip to content

Workspace

Workspace 是多轮任务的持久信息边界。当任务信息需要跨 turn 保留,但不应该塞进 prompt、Session 历史或紧凑 execution state 时,使用 Workspace。

Workspace V1 是底层能力。它负责存储和索引 record;它不决定模型应该记住什么, 也不决定下一步要执行什么。默认 Agent 和 TriggerFlow execution 都内置 lazy Workspace binding,因此标准 Agent facade 上始终可以访问 agent.workspace,默认 flow.create_execution() 也可以通过 data.require_resource("workspace") 使用 execution 专属 Workspace。默认 local backend 只会在代码第一次写入、读取、 checkpoint、记录 evidence 或暴露 Workspace 文件区时 materialize。

python
agent = Agently.create_agent("repo-worker")

ref = await agent.workspace.ingest(
    content=pytest_output,
    collection="observations",
    kind="test_output",
    summary="pytest failed in route fallback test",
    scope={"task_id": "issue-123", "turn": 1},
    source={"type": "command", "name": "pytest"},
)

records = await agent.workspace.search(
    "route fallback",
    filters={"collection": "observations", "kind": "test_output"},
)

context_pack = await agent.workspace.build_context(
    goal="Fix the route fallback failure.",
    scope={"task_id": "issue-123"},
    budget={"tokens": 12000},
    profile="software_dev",
)

应用需要稳定显式 root、read-only mode 或已注册 backend provider 时,再使用 agent.use_workspace(...)

python
agent.use_workspace("./.agently/runs/issue-123")

独立 Workspace 可以直接创建,也可以通过 Agently factory 创建:

python
from agently import Agently, Workspace

shared_workspace = Workspace("./.agently/projects/issue-123")
factory_workspace = Agently.create_workspace("./.agently/projects/issue-124")

当多个 Agent、TriggerFlow execution 或 service worker 需要共享任务信息时,优先 由应用显式创建并管理一个公共 Workspace,再把每个消费者绑定到这个 Workspace。 这是推荐的信息共享形态:Workspace 保持为持久底座,而不是隐式全局单例。

python
shared_workspace = Agently.create_workspace("./.agently/projects/issue-123")

agent = Agently.create_agent("repo-worker").use_workspace(shared_workspace)
execution = flow.create_execution(workspace=shared_workspace)

flow.create_execution() 默认创建 execution 专属 lazy Workspace。传 workspace=False 可以显式关闭;传 Workspace 实例、路径或 backend 时,execution 会使用应用自己管理的共享 Workspace。

不要依赖多个默认 Workspace 之间自动通讯。如果 TriggerFlow execution 过程中需要在 隔离 Workspace 之间移动信息,应在业务逻辑里显式完成:从源 Workspace search/read, 再写入或 ingest 到目标 Workspace,并把生成的 refs link 起来。Workspace 本身不提供 跨空间 messaging 或 replication 协议。

存什么

observations、decisions、artifacts 和紧凑 checkpoints 都可以作为 records。大型命令 输出、生成报告、transcript 和 patch 应存为 Workspace 内容,runtime state 里只保留 record refs。

python
checkpoint_ref = await agent.workspace.checkpoint(
    "issue-123",
    {"phase": "debugging", "refs": [ref]},
    step_id="run-tests",
)

state = await agent.workspace.get_data(checkpoint_ref)
latest = await agent.workspace.latest_checkpoint("issue-123")
history = await agent.workspace.checkpoint_history("issue-123")

get(...) 按文本读取已存内容。record 中保存 dict、list 或 checkpoint state 等 JSON-compatible 结构化数据时,使用 get_data(...) 取回结构化对象。

持久 Provider 读取

默认 local Workspace backend 也提供单节点开发和本地重启恢复所需的 durable-provider contract。runtime state 需要引用大型内容时,使用稳定 ref envelope,而不是复制全文。

python
ref_envelope = await agent.workspace.ref_envelope(ref)
segment = await agent.workspace.read_bounded(ref, offset=0, limit=4096)

async for chunk in agent.workspace.stream_read(ref, chunk_size=8192):
    process(chunk["content"])

ref_envelope 包含 Workspace id、record id、collection、content ref、digest、 size、创建时间、policy labels 和 backend capability hints。read_bounded(...)stream_read(...) 支持按片段读取大型 record,因此 execution state 可以只保存 refs,恢复逻辑只读取需要的部分。

当 TriggerFlow 或应用 execution 需要重启诊断,而又不能把 DevTools 当作事实来源时, 可以把 RuntimeEvent 存成持久 record:

python
execution = flow.create_execution(workspace=agent.workspace)
snapshot_ref = await execution.async_save(step_id="review")

event_record = await agent.workspace.append_runtime_event(
    "issue-123-execution",
    {"event_type": "triggerflow.interrupt_raised", "payload": {"id": "approval"}},
    idempotency_key="approval-request-1",
    snapshot_ref=snapshot_ref,
    artifact_refs=[ref],
)

events = await agent.workspace.query_runtime_events(
    "issue-123-execution",
    sequence_from=event_record["sequence"],
)

RuntimeEvent 存储会保留每个 execution 内的 sequence、idempotency key、 state version、parent event id、causation id、parent signal id、aggregation scope、operator id、interrupt id、resume request id、actor id、lease owner id、 snapshot refs、artifact refs 和 exchange id。分布式 provider 需要 fail-closed append 顺序时使用 expected_sequence=...;callback 或 webhook 重试安全使用 idempotency_key=...。Workspace 不决定 pause/resume、approval、retry 或 DAG readiness;这些语义仍由 TriggerFlow、PolicyApproval、ExecutionExchange 和 AgentExecution 所有。

Workspace-backed durable provider 也提供 TriggerFlow-facing snapshot CAS、lease 和 artifact-ref helpers:

python
snapshot_ref = await agent.workspace.put_snapshot(
    execution.run_context.run_id,
    execution.save(),
    expected_state_version=previous_state_version,
)

lease = await agent.workspace.claim_lease(
    execution.run_context.run_id,
    "worker-1",
    ttl=30.0,
    expected_state_version=snapshot_state_version,
)
await agent.workspace.heartbeat_lease(
    execution.run_context.run_id,
    "worker-1",
    lease["lease_token"],
)

artifact_ref = await agent.workspace.put_artifact_ref(
    execution.run_context.run_id,
    large_payload,
    metadata={"kind": "snapshot_payload"},
)

expected_state_version=... 会在最新 checkpoint state version 与调用方读到的 cursor 不一致时 fail closed。Lease methods 在所选 provider 内检查 owner 和 token。 local backend 提供这个单节点 durable-provider seam,用于开发和本地重启恢复;生产级 跨 worker 保证仍属于所选 backend。

Links 用来记录 records 之间的 typed relationship,并且可以通过公开 API 查询, 不需要直接访问 backend 存储。

python
decision_ref = await agent.workspace.put(
    {"decision": "Patch route fallback"},
    collection="decisions",
    kind="loop_decision",
    scope={"task_id": "issue-123"},
)

await agent.workspace.link(decision_ref, ref, relation="responds_to")
links = await agent.workspace.links(source=decision_ref, relation="responds_to")

capabilities = agent.workspace.capabilities()

link_evidence(...)link(...) 上的一层便利封装,会把 execution id、 operation id、RuntimeEvent id、checkpoint id、exchange id 和 artifact refs 记录到 link metadata。Retention anchors 可在 compaction 后保留 lineage 与 summary refs:

python
await agent.workspace.link_evidence(
    request_ref,
    result_ref,
    relation="resulted_in",
    execution_id="issue-123-execution",
    runtime_event_id=event_record["event_id"],
    checkpoint_id=checkpoint_ref["id"],
    artifact_refs=[ref],
)

await agent.workspace.add_retention_anchor(
    "issue-123-execution",
    anchor_type="compaction",
    record_ref=ref,
    preserved_event_ids=[event_record["event_id"]],
)

capabilities() 会报告当前 backend 的 content、metadata、checkpoint、 RuntimeEvent storage、ref resolution、retention policy、text index、policy 和 vector index 组件。它也会报告 supports_event_sequencesupports_range_readsupports_stream_readsupports_retentionsupports_compaction_anchorsupports_cassupports_leasesupports_artifact_refssupports_remote_backend 等 capability flags。分布式恢复应在所选 provider 缺少必要 flags 或对应 provider methods 时 fail closed。

Action 边界

agent.workspace.files_root 是给 shell、Node.js 和文件 action 使用的普通可编辑作业区。 类文件系统的 Action helper 在没有显式 root 或 cwd 时会继承这个边界,包括 Agent 仍在 使用 lazy default Workspace 时。agent.workspace.content_root 仍然是 Workspace records 使用的受管内容存储。

python
agent.enable_workspace_file_actions(write=True)
agent.enable_shell(commands=["pwd", "pytest"])
agent.enable_nodejs()

enable_workspace_file_actions(...) 不创建第二个 Workspace;它只是把当前 Workspace 文件作业区暴露成 list/search/read/write 文件 actions。只有某个 action 必须使用独立目录时, 才显式传入 root=cwd=

文件边界 policy metadata 可以持久化用于审计,但 Workspace 不因此变成 cwd manager:

python
await agent.workspace.record_file_policy(
    allowed_roots=[str(agent.workspace.files_root)],
    root_source="workspace",
    policy_labels=["customer-data"],
)

不是记忆策略

Workspace V1 不暴露 remember(...)observe(...)decide(...) 这类可被模型调用 的记忆动词。这些属于未来 Action、Recall 或 WorkLoop 层的高阶接口。V1 中,应用代码 决定写入什么;Recall 骨架通过可插拔 planner、retriever 和 context-builder profile 把已存 records 打包成 ContextPack

插件边界

Workspace 暴露 content、metadata、checkpoint、RuntimeEvent storage、ref resolution、retention、evidence links、text index、policy 和 vector index 等底层 backend seam。默认本地 backend 是 filesystem content + SQLite metadata/FTS + NoopVectorIndex。Recall 暴露 RecallPlannerRetrieverContextBuilder; 高级模型辅助规划、向量检索、rerank、compression 和 remote backends 预期作为插件叠加在这个底座上。

只要实现 Workspace backend protocol,自定义 backend 可以直接传给 agent.use_workspace(...),也可以按名称注册:

python
Agently.workspace.register_backend_provider("audit", build_audit_backend)

agent = (
    Agently.create_agent("repo-worker")
    .use_workspace(
        "tenant-a",
        provider="audit",
        provider_options={"tenant_id": "tenant-a"},
    )
)

Provider factory 会收到 rootcreatemode 和所有 provider_options, 并返回一个 WorkspaceBackend。未注册的 provider name 会 fail fast,而不是回落到 local backend。没有显式选择 provider 时,Agent 的 lazy default Workspace 会使用 .agently/workspaces/<agent-name>-<agent-id> 下的 local backend。测试套件已经包含一个 协议级 remote audit provider proof,覆盖与本地 backend 相同的 checkpoint、RuntimeEvent、 evidence link 和 capability 路径。这个 proof 不等于公开 Redis、Postgres 或 object-storage adapter;生产 provider 仍必须报告真实能力,并在缺少分布式恢复要求时 fail closed。 TriggerFlow 测试也会通过 provider 读回 Workspace-backed execution snapshot,并由 TriggerFlow 自己 load pause/continue、policy approval waits 与 when(..., mode="and") join progress,因此 Workspace 仍是 storage,不是 workflow control plane。

examples/workspace/workspace_loop_foundation.py 展示了一个显式 TriggerFlow loop:写入结构化 observations,把 decisions link 到 evidence,checkpoint 紧凑状态, 并通过 Recall 生成 ContextPack。

examples/workspace/workspace_with_action_output.py 展示 Action 边界:file action 写入 workspace.files_root,shell action 读取该文件,应用代码把 action output 显式 ingest 为 Workspace observation,再通过 Recall 打包成 ContextPack。