Ngôn ngữ: English · Tiếng Việt · 中文
Mọi knob, mọi env var, mọi precedence rule. Nếu bạn deploy OpenSpace × OpenViking, đọc trang này từ đầu đến cuối.
Cấu hình làm việc đơn giản nhất — single-machine dev, local Viking, single user:
# OpenViking chạy với defaults; chỉ cần đảm bảo nó reachable
docker run -d -p 1933:1933 volcengine/openviking:latest
# Trong OpenSpace shell / .env của bạn
export OPENVIKING_ENABLED=true
# Tất cả thứ khác default đúng; $USER cung cấp per-user isolation
openspace --query "analyze my sales spreadsheet"Hết. Lần chạy đầu không có memory → chi phí y hệt trước. Lần chạy tương tự thứ 2 retrieve được những gì đã học.
| Variable | Default | Mục đích |
|---|---|---|
OPENVIKING_ENABLED |
(auto-detect) | Master switch. Set false để disable hoàn toàn integration. |
OPENVIKING_URL |
http://127.0.0.1:1933 |
Viking server base URL |
OPENVIKING_API_KEY |
(empty) | Optional API key gửi như header X-API-Key |
OPENVIKING_NAMESPACE |
(empty) | Team/tenant prefix cho URIs. Không bao giờ auto-derive. |
OPENVIKING_USER_ID |
(fallback chain) | Per-user prefix cho user memories |
OPENVIKING_PUSH_SKILLS |
(config default) | Override cho structured skill resource push |
OPENVIKING_MIN_SCORE |
0.0 |
Drop retrievals dưới score này (0.0–1.0) |
OPENVIKING_SCRUB_PII |
true |
Scrub secrets/PII trước khi ghi vào Viking |
Values: true / false (case-insensitive). Bất kỳ giá trị khác → xem như enabled nếu config cho phép.
Precedence:
- Explicit env var value (nếu parse được như true/false)
OpenSpaceConfig.openviking_enabled(defaultTrue)
Khi nào set false: benchmark runs, debugging, privacy-sensitive one-off tasks, khi bạn muốn zero Viking HTTP calls.
Values: Bất kỳ URL hợp lệ. Trailing slash bị strip.
Examples:
http://127.0.0.1:1933(local dev, default)http://viking.internal:1933(team LAN)https://viking.acme.corp(team deployment với TLS terminator)
Values: Bất kỳ string không rỗng. Gửi như header X-API-Key trên mọi request.
Khi nào cần: khi Viking server của bạn có config auth_mode: api_key. Trong single-user dev mode, để trống.
Rotation: Restart OpenSpace sau khi update value. Không hot reload — điều này là cố ý (hot-reload secrets tạo race windows để lợi ích nhỏ).
Values: Team/tenant identifier (alphanum, -, _, .). Sanitized khi đọc.
Effect trên URIs:
Không namespace: viking://agent/memories/tools/
Với namespace=acme: viking://tenants/acme/agent/memories/tools/
Không bao giờ auto-derive — nếu không set, URIs là global. Để ngăn trộn memory cross-team vô tình, namespace phải set tường minh.
Deployment patterns:
- Solo team/individual: để trống
- Team deployment: set trong shared
.envfile, docker-compose, systemd unit, v.v. - Multi-team shared Viking: mỗi team's deploy set value riêng
- CI-per-repo: derive trong CI config (không trong OpenSpace) và export trước khi chạy
Values: Bất kỳ string (sanitized về alphanum + -_.).
Fallback chain (first non-empty wins):
OpenSpaceConfig.openviking_user_idOPENVIKING_USER_IDenv varUSERenv var (Unix/macOS)USERNAMEenv var (Windows)- Empty string → dùng team-global user memory path
Tại sao auto-fallback về OS user: Trên single-machine dev, per-user isolation nên work mà không cần config. Nếu hai người share cùng OS user, họ nên set OPENVIKING_USER_ID tường minh tới identity của họ.
Effect trên URIs:
Không user_id: viking://tenants/acme/user/memories/preferences/
Với user_id=alice: viking://tenants/acme/user/alice/memories/preferences/
Values:
- Truthy:
1,true,yes,on - Falsy:
0,false,no,off - Bất kỳ giá trị khác → fallback về
OpenSpaceConfig.openviking_auto_push_skills(defaultTrue)
Effect: Control xem evolved SKILL.md content có được push tới Viking như structured resource qua POST /api/v1/skills. Session feedback không bị ảnh hưởng — task descriptions và tool sequences vẫn commit bất kể.
Khi nào set false:
- Skills có thể chứa customer data hoặc credentials nhạy cảm
- Team policy cấm share evolved skill content cross-agents
- Testing skill evolution trong isolation không làm ô nhiễm team Viking
- Tuân thủ quy định (data residency, v.v.)
Priority: env var override config, nhưng chỉ nếu value được nhận diện. Unknown values (ví dụ OPENVIKING_PUSH_SKILLS=maybe) fallback về config default — không off-state bất ngờ.
Values: Float trong [0.0, 1.0]. Out-of-range hoặc unparseable values fallback về config default.
Effect: Kết quả của /api/v1/search/find dưới threshold sẽ bị drop ở 2 nơi:
- Server-side — pass như field
score_thresholdtrong request payload để Viking không ship hit về. - Client-side safety net —
find_memories()trongclient.pyfilter response lại trước khi return, bảo vệ khỏi các phiên bản server ignore field này.
Khi nào set:
0.0(default) — accept mọi thứ, max recall0.5— quality-oriented deployment điển hình0.7+— high-precision deployment khi wrong memories rất đắt
Đo impact: result["viking"]["hit_counts"] sẽ hiển thị ít hit hơn khi threshold tăng; correlate với actual task quality theo thời gian.
Values:
- Truthy:
1,true,yes,on - Falsy:
0,false,no,off - Các giá trị khác → fallback về config default
Effect: Khi bật (default), mọi user-authored string được ghi vào Viking qua feedback_evolution(), feedback_negative(), hoặc push_evolved_skills() đều đi qua regex scrubber trong scrubber.py trước khi được gửi.
Patterns được redact:
| Category | Pattern coverage |
|---|---|
| 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 segments), Authorization: Bearer ... |
| Credentials | Basic-auth URLs (https://user:pass@host), RSA/EC/OpenSSH private key blocks |
| PII | Email addresses, phone numbers (strict E.164 only), SSN, IP addresses |
| Financial | Credit card numbers (Luhn-validated — non-valid numbers bỏ qua) |
Khi nào set false: Chỉ khi bạn hoàn toàn tin tưởng Viking endpoint và task content. Disable scrubber là privacy/security decision — bản thân scrubber có latency không đáng kể (~microseconds mỗi string).
Idempotent: Scrubbing text đã scrubbed cho ra kết quả giống nhau, nên re-processing là an toàn.
Tất cả env vars có config fields tương ứng cho programmatic access:
from openspace.tool_layer import OpenSpaceConfig, OpenSpace
config = OpenSpaceConfig(
llm_model="openrouter/anthropic/claude-sonnet-4.5",
# OpenViking integration
openviking_enabled=True, # bool
openviking_url="", # str, "" = dùng env
openviking_api_key="", # str, "" = dùng env
openviking_namespace="acme", # str
openviking_user_id="alice", # str, "" = fallback chain
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 — expose retrieve_memory tool (Round 6)
)
async with OpenSpace(config) as os:
result = await os.execute("my task")
# Round 6: explicit user feedback API
await os.provide_feedback(
task_id=result["task_id"],
polarity="positive", # hoặc "negative"
comment="User confirmed the response was correct",
)async def provide_feedback(
self,
task_id: str,
polarity: str, # "positive" hoặc "negative"
comment: str = "",
task_description: str = "",
tool_sequence: Optional[List[str]] = None,
) -> Dict[str, Any]Kênh feedback tường minh cho host agents và communication adapters capture user signals ("that was wrong", "try again", thumbs-up/down). Route tới Viking memory bucket đúng:
polarity="positive"→ tạo session reinforcementopenspace-rating-<task_id>polarity="negative"→ tạo session anti-patternopenspace-neg-<task_id>land vàoagent/memories/antipatterns/
Return {"status": "ok"|"skipped"|"error", "polarity": str, "session_id": str}. Best-effort: nếu Viking down, return {"status": "skipped"} thay vì raise.
Precedence: Explicit config value > env var > fallback. String rỗng trong config nghĩa là "dùng env var". String không rỗng trong config nghĩa là "ignore env var cho field này".
Function resolve_viking_identity() là single source of truth. Signature của nó:
def resolve_viking_identity(
namespace_override: str = "",
user_id_override: str = "",
) -> tuple[str, str]:Logic resolution:
namespace:
config_override (nếu non-empty)
→ OPENVIKING_NAMESPACE env
→ "" (empty = không tenant scoping)
user_id:
config_override (nếu non-empty)
→ OPENVIKING_USER_ID env
→ USER env (Unix)
→ USERNAME env (Windows)
→ "" (empty = team-global user path)
Cả hai values đều được sanitize — chỉ alphanum cộng -_. sống sót. Leading/trailing -_. bị strip.
Examples:
| config ns | config uid | env NS | env UID | env USER | Resolved |
|---|---|---|---|---|---|
"" |
"" |
"" |
"" |
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") |
Row cuối cho thấy sanitization: space và ! bị strip khỏi namespace; @ bị strip khỏi user_id nhưng . được giữ.
Tất cả Viking memory queries dùng directory-prefix URIs. Client build chúng qua agent_memory_uri(category) và 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/Không namespace, chúng fallback về:
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/Với namespace nhưng không user_id:
viking://tenants/acme/user/memories/preferences/
Không cả hai:
viking://user/memories/preferences/
Nếu bạn cần query một prefix custom:
results = await client.find_memories(
query="my search",
target_uri="viking://some/custom/path/",
limit=10,
)find_memories là low-level primitive; find_tool_knowledge, find_cases, v.v. là thin wrappers tính toán target_uri từ identity config.
# .env
OPENVIKING_ENABLED=true
# tất cả thứ khác empty — $USER cung cấp user isolation# Shared team .env (checked vào team-private config repo)
OPENVIKING_URL=http://viking.internal:1933
OPENVIKING_API_KEY=<team-key>
OPENVIKING_NAMESPACE=acme-eng
# Per-developer override trong ~/.config/openspace/.env
OPENVIKING_USER_ID=alice # optional — default về $USERAgent memories (tool knowledge, patterns, cases) shared across toàn team. Preferences của Alice không leak sang Bob.
# Team A
OPENVIKING_URL=http://viking.corp.internal:1933
OPENVIKING_NAMESPACE=team-frontend
OPENVIKING_API_KEY=<team-frontend-key>
# Team B
OPENVIKING_URL=http://viking.corp.internal:1933
OPENVIKING_NAMESPACE=team-backend
OPENVIKING_API_KEY=<team-backend-key>Mỗi team có memory namespace isolated. RBAC của chính Viking enforce API key scoping.
# .github/workflows/test.yml
env:
OPENVIKING_ENABLED: false # không làm ô nhiễm team memory từ CI runsHoặc trỏ CI tới Viking instance riêng:
env:
OPENVIKING_URL: http://ci-viking:1933
OPENVIKING_NAMESPACE: ci-runs
OPENVIKING_PUSH_SKILLS: false # không push ephemeral skillsOPENVIKING_ENABLED=true
OPENVIKING_URL=http://internal-viking
OPENVIKING_NAMESPACE=prod
OPENVIKING_PUSH_SKILLS=false # không skill content nào rời box
OPENVIKING_USER_ID=<bot-account>Session feedback (task, tools) vẫn commit cho memory extraction, nhưng evolved skill content ở lại local.
Mỗi execute() return một viking dict trong result:
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,
}Cộng với một dòng log mỗi task:
Viking telemetry: available=True hits=9 enrich_chars=1243 feedback=committed pushed=1
Grep-friendly cho quick dashboards. Xem Token Economics — Đo đạc trong production.
Template canonical ở openspace/.env.example. Section liên quan:
# ── 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
# Retrieval quality + privacy hardening (Round 6):
# OPENVIKING_MIN_SCORE=0.0
# OPENVIKING_SCRUB_PII=trueCheck theo thứ tự:
# 1. Integration có enabled không?
print(config.openviking_enabled) # phải là True
# 2. Client có được construct không?
print(openspace._viking_client) # không phải None
# 3. Server có reachable không?
available = await openspace._viking_client.is_available()
print(available) # phải là TrueNếu (3) fail, check:
curl http://127.0.0.1:1933/healthtừ OpenSpace host- Firewall rules giữa OpenSpace và Viking
OPENVIKING_URLcó port đúng (default 1933, không phải Viking port khác)
Set OPENVIKING_USER_ID tường minh per user. Fallback $USER dùng OS user name, vậy nếu hai người share cùng OS account, họ share cùng user_id.
Bạn có thể đã set OPENVIKING_NAMESPACE trong global .env rồi làm việc cá nhân mà không unset. Hoặc:
- Dùng Viking instances khác nhau (dev vs team)
- Set
OPENVIKING_NAMESPACE=personal-$USERtrong shell rc trước khi làm việc cá nhân - Bắt đầu namespace với sentinel prefix để team deploys không match ngẫu nhiên
OPENVIKING_PUSH_SKILLS=false là switch. Lưu ý session feedback vẫn commit — đây là cố ý (extracted abstracts là low-risk, SKILL.md content là higher-risk).
Nếu bạn muốn disable TOÀN BỘ feedback nữa, path sạch nhất là disable integration hoàn toàn: OPENVIKING_ENABLED=false.
Không user-configurable hôm nay, nhưng document cho contributors:
| Parameter | Value | Location |
|---|---|---|
| Request timeout | 5.0 seconds | _REQUEST_TIMEOUT trong client.py |
| Health cache TTL (success) | 60 seconds | _HEALTH_CACHE_TTL_OK |
| Health cache TTL (failure) | 12 seconds | _HEALTH_CACHE_TTL_FAIL |
| Max query length | 500 chars | _MAX_QUERY_CHARS trong enrichment.py |
| Memory fetch limit mỗi category | 3–5 (tool/pattern/skill=5, pref/case=3) | inline trong enrichment.py |
Nếu bạn cần tune chúng, fork và edit constants. Chúng cố ý không được expose như config knobs — defaults được chọn để giữ worst-case latency bounded mà không có ceremony từ user.
Tiếp theo: Operations — business rules, deployment, testing, troubleshooting.