当您隔离工作、严格限制访问范围、将元数据分开保存并有意识地对存储进行分区时,Artifacts 的效果最好。
使用这些模式为智能体(agent)、自动化程序和共享系统构建存储库结构。
为每个自治工作单元创建一个存储库。如果您有 10,000 个智能体,请创建 10,000 个存储库。
这可以保持每个智能体的更改、故障和清理生命周期相互独立。它还可以避免使单个共享存储库成为冲突、大型 diff 和意外覆盖的易发区域。
在需要执行以下操作时使用此模式:
- 将一个智能体的工作与另一个智能体的工作隔离
- 将存储库移交给单个会话或用户应用
- 独立地查看、合并、归档或删除工作
仅在协作者共享相同的生命周期且需要在同一个存储库上工作时才使用分支。不要将一个共享存储库用作许多自治智能体的队列。
存储库名称在命名空间内是唯一的。如果多个智能体在一个命名空间中需要同一个基线存储库的隔离副本,请不要重复使用简短的共享名称(例如 docs-site)。
在存储库名称中包含稳定的标识符,例如智能体名称、会话 ID、用户 ID 或工作流 ID。像 ${agentName}-${sessionId}-${repoName} 这样的名称比 ${repoName} 更安全,因为它可以避免冲突并使清理更容易。
此示例在创建存储库之前创建了一个唯一的存储库名称。
async function createRepoCopy(env, agentName, sessionId, repoName) {
const uniqueRepoName = `${agentName}-${sessionId}-${repoName}`;
return env.ARTIFACTS.create(uniqueRepoName);
}interface Env {
ARTIFACTS: Artifacts;
}
async function createRepoCopy(
env: Env,
agentName: string,
sessionId: string,
repoName: string,
) {
const uniqueRepoName = `${agentName}-${sessionId}-${repoName}`;
return env.ARTIFACTS.create(uniqueRepoName);
}当智能体需要相同的入门文件、提示词(prompt)或应用结构时,从受信任的基线开始创建新的存储库。从经过审查的存储库中进行分叉,比手动将文件复制到每个新存储库中更安全。
这可以保持您的起点一致,并使下游 diff 更易于审查。它还允许您仅合并回您想要的结果。
此示例将经过审查的基线存储库分叉到特定于会话的存储库中。
async function forkFromBaseline(env, sessionId) {
const baseline = await env.ARTIFACTS.get("starter-repo");
const forked = await baseline.fork(`starter-repo-${sessionId}`, {
description: `Fork for session ${sessionId}`,
defaultBranchOnly: true,
readOnly: false,
});
return {
name: forked.name,
remote: forked.remote,
};
}interface Env {
ARTIFACTS: Artifacts;
}
async function forkFromBaseline(env: Env, sessionId: string) {
const baseline = await env.ARTIFACTS.get("starter-repo");
const forked = await baseline.fork(`starter-repo-${sessionId}`, {
description: `Fork for session ${sessionId}`,
defaultBranchOnly: true,
readOnly: false,
});
return {
name: forked.name,
remote: forked.remote,
};
}Artifacts 令牌是在存储库范围内生效的。克隆、索引、审查和检索时请首选 read 令牌。
仅为必须推送(push)更改的智能体或系统使用 write 令牌。缩短令牌的生存期,并为每个智能体会话重新签发新的令牌。
此示例使用 Workers 绑定(binding) 为存储库生成一个短期读取令牌。
在路由返回令牌之前,假设调用方已通过身份验证和授权。
export default {
async fetch(request, env) {
const url = new URL(request.url);
const repoName = url.searchParams.get("repo") ?? "starter-repo";
const repo = await env.ARTIFACTS.get(repoName);
const token = await repo.createToken("read", 900);
return Response.json({
repo: repoName,
scope: token.scope,
expiresAt: token.expiresAt,
token: token.plaintext,
});
},
};interface Env {
ARTIFACTS: Artifacts;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const repoName = url.searchParams.get("repo") ?? "starter-repo";
const repo = await env.ARTIFACTS.get(repoName);
const token = await repo.createToken("read", 900);
return Response.json({
repo: repoName,
scope: token.scope,
expiresAt: token.expiresAt,
token: token.plaintext,
});
},
} satisfies ExportedHandler<Env>;只有在您的 Worker 授权了必须推送更改的会话之后,才对 write 令牌使用相同的模式。
不要向每个智能体签发一个长期有效的写入令牌。请在尽可能短的时间内签发权限最小的令牌。
使用 git notes ↗ 将提示词(prompt)、模型输出、运行 ID 或其他框架元数据附加到提交上,而无需更改提交对象或工作树。
这使您可以将 Artifacts 既用作智能体工作的版本化文件系统,又用作智能体框架的唯一事实来源。您的文件保持专注于工作产品,而提交说明(commit notes)则保存了周围 Graves的执行上下文。
此示例将用户提示词和助手摘要存储在当前提交上,然后重新读取该说明。
git notes add -m 'user: Add a best-practices section for unique repo names.' HEAD
git notes append -m 'assistant: Added naming guidance and a code example.' HEAD
git notes show HEAD如果您在系统之间同步存储库,请记住 notes 存在于独立的引用(ref)上。当您希望这些元数据随存储库一起传输时,请将 refs/notes/* 与其余存储库数据一起进行推送和拉取。
使用命名空间来隔离运行边界。存储库隔离可以隔离工作单元,而命名空间隔离则可以隔离所有权、环境和流量模式。
一旦使用量增长,请不要将所有存储库都保留在一个默认命名空间中。当您需要更清晰的所有权或在每个命名空间的请求速率限制内拥有更多扩展空间时,请拆分命名空间。
| 使用场景 | 示例命名空间 | 原因 |
|---|---|---|
| 环境 | staging, prod |
保持测试流量和生产流量分离。 |
| 团队边界 | sales, finance, devtools |
保持所有权、访问权限和清理策略不同。 |
| 流量隔离 | agents-batch, agents-realtime |
防止一个工作负载消耗另一个工作负载的限制。 |
当一个命名空间变得繁忙时,将新存储库分片到其他命名空间中,而不是继续扩大单个共享命名空间。