语言: English · Tiếng Việt · 中文
每个开关、每个环境变量、每条优先级规则。如果你正在部署 OpenSpace × OpenViking,请从头到尾读完本页。
最简单可工作的配置 —— 单机开发、本地 Viking、单用户:
# OpenViking 使用默认配置运行;只需确保可达
docker run -d -p 1933:1933 volcengine/openviking:latest
# 在你的 OpenSpace shell / .env 中
export OPENVIKING_ENABLED=true
# 其他所有配置默认正确;$USER 提供按用户隔离
openspace --query "分析我的销售电子表格"就这样。第一次运行没有记忆 → 和之前成本相同。第二次相似运行会检索到已学到的东西。
| 变量 | 默认 | 作用 |
|---|---|---|
OPENVIKING_ENABLED |
(自动检测) | 总开关。设为 false 完全禁用集成。 |
OPENVIKING_URL |
http://127.0.0.1:1933 |
Viking 服务器 base URL |
OPENVIKING_API_KEY |
(空) | 可选 API key,作为 X-API-Key header 发送 |
OPENVIKING_NAMESPACE |
(空) | URI 的团队/租户前缀。永不自动推断。 |
OPENVIKING_USER_ID |
(回退链) | 用户记忆的按用户前缀 |
OPENVIKING_PUSH_SKILLS |
(config default) | 覆盖结构化 skill 资源推送 |
OPENVIKING_MIN_SCORE |
0.0 |
丢弃分数低于此阈值的检索(0.0–1.0) |
OPENVIKING_SCRUB_PII |
true |
在写入 Viking 前清理 secrets/PII |
值:true / false(大小写不敏感)。其他任何值 → 如果 config 允许就视为启用。
优先级:
- 明确的环境变量值(如果能解析为 true/false)
OpenSpaceConfig.openviking_enabled(默认True)
何时设为 false:benchmark 运行、调试、隐私敏感的一次性 task、当你想要零 Viking HTTP 调用时。
值:任何有效 URL。尾部斜杠会被剥离。
示例:
http://127.0.0.1:1933(本地开发,默认)http://viking.internal:1933(团队局域网)https://viking.acme.corp(带 TLS terminator 的团队部署)
值:任何非空字符串。在每个请求上作为 X-API-Key header 发送。
何时需要:当你的 Viking 服务器配置了 auth_mode: api_key 时。在单用户开发模式下留空。
轮转:更新值后重启 OpenSpace。没有热重载 —— 这是故意的(热重载 secret 会引入 race window,收益极小)。
值:团队/租户标识符(字母数字、-、_、.)。读取时会被清理。
对 URI 的影响:
无 namespace: viking://agent/memories/tools/
namespace=acme: viking://tenants/acme/agent/memories/tools/
永不自动推断 —— 如果未设置,URI 是全局的。为了防止跨团队意外混淆记忆,必须明确设置 namespace。
部署模式:
- 单团队/个人:留空
- 团队部署:在共享的
.env文件、docker-compose、systemd unit 等中设置 - 多团队共享 Viking:每个团队的部署设置自己的值
- CI-per-repo:在 CI 配置中推导(而不是在 OpenSpace 内部)并在运行前 export
值:任何字符串(清理为字母数字 + -_.)。
回退链(第一个非空胜出):
OpenSpaceConfig.openviking_user_idOPENVIKING_USER_ID环境变量USER环境变量(Unix/macOS)USERNAME环境变量(Windows)- 空字符串 → 使用团队级全局用户记忆路径
为什么自动回退到 OS 用户:在单机开发中,按用户隔离应该无需配置就能工作。如果两个人共用同一个 OS 用户,他们应该明确设置 OPENVIKING_USER_ID 为各自身份。
对 URI 的影响:
无 user_id: viking://tenants/acme/user/memories/preferences/
user_id=alice: viking://tenants/acme/user/alice/memories/preferences/
值:
- 真值:
1、true、yes、on - 假值:
0、false、no、off - 其他任何值 → 回退到
OpenSpaceConfig.openviking_auto_push_skills(默认True)
作用:控制是否将进化后的 SKILL.md 内容通过 POST /api/v1/skills 作为结构化资源推送到 Viking。Session 反馈不受影响 —— task 描述和工具序列仍然会 commit。
何时设为 false:
- Skill 可能包含敏感客户数据或凭证
- 团队政策禁止跨 Agent 共享进化 skill 内容
- 在隔离环境中测试 skill 进化,不污染团队 Viking
- 监管合规(数据驻留等)
优先级:环境变量覆盖 config,但仅当值可识别时。未知值(例如 OPENVIKING_PUSH_SKILLS=maybe)回退到 config 默认 —— 不会意外关闭。
值:[0.0, 1.0] 范围内的 float。超出范围或无法解析的值回退到 config 默认。
效果:/api/v1/search/find 返回的分数低于阈值的结果会在两处被丢弃:
- 服务器端 —— 作为
score_threshold字段传入请求 payload,Viking 直接不返回该命中。 - 客户端安全网 ——
client.py中的find_memories()在返回前再次过滤响应,防止服务器版本忽略该字段。
何时设置:
0.0(默认)—— 接受一切,最大召回0.5—— 典型的质量导向部署0.7+—— 错误记忆代价非常高的高精度部署
测量影响:随着阈值提高,result["viking"]["hit_counts"] 会显示更少的命中;与实际任务质量在时间维度上关联。
值:
- 真值:
1、true、yes、on - 假值:
0、false、no、off - 其他任何值 → 回退到 config 默认
效果:启用时(默认),通过 feedback_evolution()、feedback_negative() 或 push_evolved_skills() 写入 Viking 的每个用户编写字符串都会在发送前通过 scrubber.py 中的正则清理器。
被 redact 的模式:
| 类别 | 模式覆盖 |
|---|---|
| API keys | Anthropic (sk-ant-*)、OpenAI (sk-proj-*, sk-*)、OpenRouter (sk-or-*)、GitHub (ghp_*, github_pat_*)、AWS (AKIA*, ASIA*)、GCP (AIza*)、Slack (xox*) |
| Tokens | JWT(3 个 base64 段)、Authorization: Bearer ... |
| 凭证 | Basic-auth URL(https://user:pass@host)、RSA/EC/OpenSSH 私钥块 |
| PII | 邮箱地址、电话号码(仅严格 E.164)、SSN、IP 地址 |
| 金融 | 信用卡号(Luhn 校验 —— 校验失败的数字不处理) |
何时设置 false:仅当你完全信任 Viking 端点和任务内容。禁用清理器是一个隐私/安全决策 —— 清理器本身的延迟可忽略(每字符串约微秒级)。
幂等:对已清理的文本再次清理产生相同的结果,所以重复处理是安全的。
所有环境变量都有对应的 config 字段用于编程访问:
from openspace.tool_layer import OpenSpaceConfig, OpenSpace
config = OpenSpaceConfig(
llm_model="openrouter/anthropic/claude-sonnet-4.5",
# OpenViking 集成
openviking_enabled=True, # bool
openviking_url="", # str,"" = 使用 env
openviking_api_key="", # str,"" = 使用 env
openviking_namespace="acme", # str
openviking_user_id="alice", # str,"" = 回退链
openviking_auto_push_skills=True, # bool
openviking_min_score=0.0, # float, 0.0–1.0 (Round 6)
openviking_scrub_pii=True, # bool (Round 6)
openviking_mid_iter_tool=True, # bool — 暴露 retrieve_memory 工具 (Round 6)
)
async with OpenSpace(config) as os:
result = await os.execute("我的 task")
# Round 6: 明确的用户反馈 API
await os.provide_feedback(
task_id=result["task_id"],
polarity="positive", # 或 "negative"
comment="User confirmed the response was correct",
)async def provide_feedback(
self,
task_id: str,
polarity: str, # "positive" 或 "negative"
comment: str = "",
task_description: str = "",
tool_sequence: Optional[List[str]] = None,
) -> Dict[str, Any]为 host agent 和 communication adapter 捕获用户信号("that was wrong"、"try again"、thumbs-up/down)的明确反馈通道。路由到正确的 Viking 记忆桶:
polarity="positive"→ 创建 reinforcement sessionopenspace-rating-<task_id>polarity="negative"→ 创建 anti-pattern sessionopenspace-neg-<task_id>,落到agent/memories/antipatterns/
返回 {"status": "ok"|"skipped"|"error", "polarity": str, "session_id": str}。Best-effort:如果 Viking 挂了,返回 {"status": "skipped"} 而不是 raise。
优先级:明确的 config 值 > 环境变量 > 回退。config 中的空字符串意味着"使用环境变量"。config 中的非空字符串意味着"忽略此字段的环境变量"。
函数 resolve_viking_identity() 是单一真源。它的签名:
def resolve_viking_identity(
namespace_override: str = "",
user_id_override: str = "",
) -> tuple[str, str]:解析逻辑:
namespace:
config_override (如果非空)
→ OPENVIKING_NAMESPACE env
→ ""(空 = 无租户作用域)
user_id:
config_override (如果非空)
→ OPENVIKING_USER_ID env
→ USER env(Unix)
→ USERNAME env(Windows)
→ ""(空 = 团队级全局用户路径)
两个值都会被清理 —— 只有字母数字加 -_. 被保留。前导/尾部的 -_. 被剥离。
示例:
| config ns | config uid | env NS | env UID | env USER | 解析结果 |
|---|---|---|---|---|---|
"" |
"" |
"" |
"" |
jimmy |
("", "jimmy") |
"acme" |
"" |
"" |
"" |
jimmy |
("acme", "jimmy") |
"" |
"" |
"acme" |
"alice" |
jimmy |
("acme", "alice") |
"override" |
"" |
"env-ns" |
"" |
jimmy |
("override", "jimmy") |
"" |
"override" |
"" |
"env-uid" |
jimmy |
("", "override") |
"acme corp!" |
"alice@corp" |
— | — | — | ("acmecorp", "alice.corp") |
最后一行展示了清理:namespace 中的空格和 ! 被剥离;user_id 中的 @ 被剥离但 . 保留。
所有 Viking 记忆查询都使用目录前缀 URI。client 通过 agent_memory_uri(category) 和 user_memory_uri(category) 构建:
c = OpenVikingClient(namespace="acme")
c.agent_memory_uri("tools") # viking://tenants/acme/agent/memories/tools/
c.agent_memory_uri("patterns") # viking://tenants/acme/agent/memories/patterns/
c.agent_memory_uri("skills") # viking://tenants/acme/agent/memories/skills/
c.agent_memory_uri("cases") # viking://tenants/acme/agent/memories/cases/无 namespace 时回退到:
viking://agent/memories/tools/
viking://agent/memories/patterns/
...
c = OpenVikingClient(namespace="acme", user_id="alice")
c.user_memory_uri("preferences") # viking://tenants/acme/user/alice/memories/preferences/
c.user_memory_uri("profile") # viking://tenants/acme/user/alice/memories/profile/有 namespace 但无 user_id:
viking://tenants/acme/user/memories/preferences/
两者都没有:
viking://user/memories/preferences/
如果你需要查询自定义前缀:
results = await client.find_memories(
query="我的搜索",
target_uri="viking://some/custom/path/",
limit=10,
)find_memories 是底层原语;find_tool_knowledge、find_cases 等是薄包装器,从身份配置中计算 target_uri。
# .env
OPENVIKING_ENABLED=true
# 其他所有都为空 —— $USER 提供用户隔离# 共享的团队 .env(提交到团队私有配置仓库)
OPENVIKING_URL=http://viking.internal:1933
OPENVIKING_API_KEY=<team-key>
OPENVIKING_NAMESPACE=acme-eng
# ~/.config/openspace/.env 中每个开发者的覆盖
OPENVIKING_USER_ID=alice # 可选 —— 默认为 $USERAgent 记忆(工具知识、模式、案例)在整个团队共享。Alice 的偏好不会泄漏到 Bob。
# 团队 A
OPENVIKING_URL=http://viking.corp.internal:1933
OPENVIKING_NAMESPACE=team-frontend
OPENVIKING_API_KEY=<team-frontend-key>
# 团队 B
OPENVIKING_URL=http://viking.corp.internal:1933
OPENVIKING_NAMESPACE=team-backend
OPENVIKING_API_KEY=<team-backend-key>每个团队有隔离的记忆 namespace。Viking 自身的 RBAC 强制 API key 作用域。
# .github/workflows/test.yml
env:
OPENVIKING_ENABLED: false # 不要让 CI 运行污染团队记忆或把 CI 指向专用的 Viking 实例:
env:
OPENVIKING_URL: http://ci-viking:1933
OPENVIKING_NAMESPACE: ci-runs
OPENVIKING_PUSH_SKILLS: false # 不推送临时 skillOPENVIKING_ENABLED=true
OPENVIKING_URL=http://internal-viking
OPENVIKING_NAMESPACE=prod
OPENVIKING_PUSH_SKILLS=false # 没有 skill 内容离开机器
OPENVIKING_USER_ID=<bot-account>Session 反馈(task、tools)仍然会 commit 用于记忆抽取,但进化后的 skill 内容留在本地。
每次 execute() 在 result 中返回一个 viking 字典:
result["viking"] == {
"enabled": bool,
"available": bool,
"query": str,
"enrichment_chars": int,
"hit_counts": {
"tool_hints": int,
"pattern_hints": int,
"skill_hints": int,
"user_preferences": int,
"case_hints": int,
},
"selector_hints_chars": int,
"analysis_context_used": bool,
"feedback_status": "skipped" | "attempted" | "committed" | "failed" | "disabled",
"pushed_skills": int,
}外加每 task 一行日志:
Viking telemetry: available=True hits=9 enrich_chars=1243 feedback=committed pushed=1
方便 dashboard grep。见 Token 经济学 —— 生产环境测量。
权威模板在 openspace/.env.example。相关部分:
# ── OpenViking Integration (optional) ───────────────────────
# Connect to OpenViking context database for cross-session memory.
# If OpenViking server is not running, OpenSpace works normally without it.
# OPENVIKING_URL=http://127.0.0.1:1933
# OPENVIKING_API_KEY=
# OPENVIKING_ENABLED=true
# Multi-team / multi-user scoping (optional):
# OPENVIKING_NAMESPACE=
# OPENVIKING_USER_ID=
# Skill resource push (privacy toggle):
# OPENVIKING_PUSH_SKILLS=true
# 检索质量 + 隐私加固(Round 6):
# OPENVIKING_MIN_SCORE=0.0
# OPENVIKING_SCRUB_PII=true按顺序检查:
# 1. 集成启用了吗?
print(config.openviking_enabled) # 应该是 True
# 2. Client 构建了吗?
print(openspace._viking_client) # 应该不是 None
# 3. 服务器可达吗?
available = await openspace._viking_client.is_available()
print(available) # 应该是 True如果 (3) 失败,检查:
- 从 OpenSpace 主机上
curl http://127.0.0.1:1933/health - OpenSpace 和 Viking 之间的防火墙规则
OPENVIKING_URL有正确的端口(默认 1933,不是其他 Viking 端口)
为每个用户明确设置 OPENVIKING_USER_ID。$USER 回退使用 OS 用户名,所以如果两个人共享同一个 OS 账户,他们共享同一个 user_id。
你可能在全局 .env 中设置了 OPENVIKING_NAMESPACE,然后做个人工作时没有 unset。要么:
- 使用不同的 Viking 实例(dev vs 团队)
- 在个人工作前在 shell rc 中设置
OPENVIKING_NAMESPACE=personal-$USER - 用哨兵前缀开头 namespace,让团队部署不会意外匹配
OPENVIKING_PUSH_SKILLS=false 是开关。注意 session 反馈仍然 commit —— 这是故意的(抽取的 abstract 是低风险,SKILL.md 内容是更高风险)。
如果你想禁用所有反馈,最干净的路径是完全禁用集成:OPENVIKING_ENABLED=false。
目前不是用户可配置的,但为 contributor 文档化:
| 参数 | 值 | 位置 |
|---|---|---|
| 请求超时 | 5.0 秒 | client.py 中的 _REQUEST_TIMEOUT |
| 健康缓存 TTL(成功) | 60 秒 | _HEALTH_CACHE_TTL_OK |
| 健康缓存 TTL(失败) | 12 秒 | _HEALTH_CACHE_TTL_FAIL |
| 最大查询长度 | 500 字符 | enrichment.py 中的 _MAX_QUERY_CHARS |
| 每类记忆获取 limit | 3–5(tool/pattern/skill=5, pref/case=3) | enrichment.py 内联 |
如果你需要调优这些,fork 并编辑常量。它们故意没有暴露为 config 开关 —— 默认值的选择是为了在无需用户干预的情况下保持最坏情况延迟有界。
下一页:运维 —— 业务规则、部署、测试、故障排查。