管理上下文

使用标签整理内容

Memory、Experience、Skill 和 Handoff 都可以在各自 Scope 内设置标签。一个 Memory 制品与其中的每条逻辑记忆分别拥有独立的标签集合。 标签跟随逻辑 ID,不会修改内容 Revision、条目版本、血缘、向量或 Context Version。

Prompt 配置不属于标签对象,其内容和历史版本仍通过 Scope 下的提示词接口查看。

开启访问控制时,标签遵循所属对象的读取与修改权限。只读分享者可以读取该对象的标签,不能修改标签或执行 Scope 级标签查询。 跨对象查询需要 scope.read;Memory 制品整体标签需要 scope.read 才能读取、scope.admin 才能修改, 单条记忆的标签则使用该条目的 artifact.read / artifact.write 权限。权限不足返回 403,撤销分享后立即失去相应标签访问权限。

标签通过下文的 Python Client 或公开 API 管理。Dashboard 用于阅读已保存内容,不提供标签编辑和查询页面。

使用 Python Client

需要一个运行中的 Server,以及已有的 Scope 和制品。请从 Dashboard 或对应 API 获取 ID,不能用标题代替 ID。 在终端设置以下非敏感参数:

export POWERCONTEXT_TAG_SCOPE='已有的-scope-id'
export POWERCONTEXT_TAG_FAMILY='skill'
export POWERCONTEXT_TAG_ARTIFACT='已有的-artifact-id'

在已安装 powercontext 的环境中运行下面的代码。若 Server 开启认证,通过 POWERCONTEXT_SERVER_AUTH_TOKEN 提供 bearer token, 不要把凭据写进代码。

import asyncio
import os

from powercontext.client import PowerContextClient
from powercontext.http import QueryArtifactTagsRequest, ReplaceArtifactTagsRequest


async def main():
    scope = os.environ["POWERCONTEXT_TAG_SCOPE"]
    family = os.environ["POWERCONTEXT_TAG_FAMILY"]
    artifact = os.environ["POWERCONTEXT_TAG_ARTIFACT"]
    async with PowerContextClient(
        "http://127.0.0.1:8000", token=os.getenv("POWERCONTEXT_SERVER_AUTH_TOKEN")
    ) as client:
        current = await client.get_artifact_tags(scope, family, artifact)
        if current is None:
            raise RuntimeError("An unconditional read must return the current tag set")
        saved = await client.replace_artifact_tags(
            scope, family, artifact,
            ReplaceArtifactTagsRequest.model_validate({"tags": ["customer-a", "release"]}),
            expected_etag=current.etag,
        )
        print(saved.tag_set.model_dump(mode="json")["tags"])
        matches = await client.query_artifact_tags(
            scope, QueryArtifactTagsRequest.model_validate({"tags": ["CUSTOMER-A"]})
        )
        print([item.target.model_dump(mode="json") for item in matches.items])


asyncio.run(main())

输出应包含保存的两个标签和匹配的对象。对记忆条目,使用 get_memory_entry_tagsreplace_memory_entry_tags, 传入 (scope_id, artifact_id, entry_id)。entry ID 来自当前 manifest 或 Memory citation,不是 entry_version_id。 一个 Scope 可以有多个 Memory 制品;已有的 Scope 级记忆列表和检索接口操作的是运行时指定的 Memory。

HTTP 接口与检索过滤

MethodPath用途
GET / PUT/v1/scopes/{scope_id}/artifacts/{family}/{artifact_id}/tags读取或替换制品标签
GET / PUT/v1/scopes/{scope_id}/artifacts/memory/{artifact_id}/entries/{entry_id}/tags读取或替换逻辑记忆条目的标签
POST/v1/scopes/{scope_id}/artifact-tags/query跨制品类型精确查找标签对象

PUT 请求体是 {"tags":["customer-a","release"]},并且必须通过 If-Match 提交 GET 返回的 ETag。 缺少 If-Match 返回 428;标签状态过期或 ETag 属于其他对象,返回 412。 条件 GET 检测到标签未变化时返回 304tag_digest 仅描述规范化的标签集合,不能代替 HTTP 写入使用的 ETag。

制品列表支持重复的 tag 参数,以及可选的 tag_match=all|any,例如: /v1/scopes/{scope_id}/artifacts/skill?tag=release&tag=customer-a&tag_match=all。 没有 tag 时不能单独传入 tag_match

记忆条目列表和检索请求支持以下可选字段:

{"tag_filter":{"tags":["customer-a","release"],"match":"all"}}

记忆检索匹配的是条目自己的标签,不是所属 Memory 制品的标签,且仍然只返回活跃条目。 全文与向量通道都在数据库候选集阶段过滤,之后才应用候选数量限制、融合与重排。 SQLite 和 OceanBase 的带标签向量查询会对符合条件的集合进行精确距离排序,成本可能高于不带标签的近似搜索。 不支持标签过滤的后端会明确拒绝请求,不会静默改成先截断再过滤。

标签查询返回当前的精确 Artifact 引用或 Memory citation,按制品类型、对象类型、制品 ID、对象 ID 排序。 翻页时原样传回 next_cursor,并保持 Scope、过滤条件和调用方一致。游标有效期是一小时;无效或不匹配返回 400, 过期返回 410。单页内部保持一致,但跨页不固定数据库快照。

标签规则与存储

  • 每个对象最多 32 个标签;一次过滤接受 1–16 个标签。
  • 每个标签包含 1–64 个 Unicode 码点,首尾不能有空白,不能包含控制字符、代理字符或未分配字符。
  • 匹配键由 NFC 规范化后再执行 Unicode case folding 得到,显示文字保留原始写法。 StraßeSTRASSE 等规范化后重复的标签会让整次请求失败;规范化键不能超过 128 个码点。
  • 标签是 Scope 内的检索元数据,不是权限或可信指令,不会进入模型提示词、Skill 包 frontmatter 或发布/导入内容。 发布后的副本不会继承源对象的标签。
  • 只要条目仍在当前权威 manifest 中,即使已经停用也可以维护标签。重建活跃搜索投影不会删除标签。

所有关联都存储在 pc_artifact_tags 一张表中,通过外键关联所属制品的 head。 表内保留完整规范化键,并使用 32 字节 SHA-256 键摘要建立索引,以同时满足 OceanBase 的外键列长度要求和 3072 字节索引限制。 匹配时同时校验摘要与完整键。相同集合的重复替换保留关联时间。已有制品无需回填,初始标签为空;备份时应包含此表, 恢复时安排在 Artifact heads 之后。

完整请求与响应结构见 Server 的 HTTP API 参考

On this page