docs/en/concepts/04-viking-uri.md
Viking URI is the unified resource identifier for all content in OpenViking.
viking://{scope}/{path}
vikingresources, user; temp, queue, and upload are internal)| Scope | Description | Lifecycle | Visibility |
|---|---|---|---|
| resources | Independent resources | Long-term | Global |
| user | User-level data, including sessions | Long-term / session lifetime | Current user |
| queue | Processing queue | Temporary | Internal |
| temp | Temporary files | During parsing | Internal |
| upload | Temporary upload files | Temporary | Internal |
Public API and CLI filesystem/content operations accept the public scopes
resources and user (plus the root URI viking://). session is retained
as a backward-compatible alias for user session paths; new session data lives
under viking://user/{user_id}/sessions.
agent is deprecated but remains as a read-only compatibility entry for legacy
agent data. temp, queue, and upload are internal implementation
scopes and cannot be addressed directly through public API URI parameters.
Moving away from traditional flat database thinking, all context is organized as a filesystem. Agents no longer just find data through vector search, but can locate and browse data through deterministic paths and standard filesystem commands. Each context or directory is assigned a unique URI identifier string in the format viking://{scope}/{path}, allowing the system to precisely locate and access resources stored in different locations.
viking://
├── user/
│ └── {user_id}/
│ ├── profile.md # User profile
│ ├── memories/ # User memory storage
│ ├── resources/ # User-owned private resources
│ ├── skills/ # User skills
│ ├── peers/
│ │ └── {peer_id}/
│ │ ├── memories/ # Memory about a specific interaction peer
│ │ └── resources/ # Resources scoped to that peer
│ └── sessions/ # User session storage
│ └── {session_id}/
│ ├── .abstract.md
│ ├── .overview.md
│ ├── .meta.json
│ ├── messages.jsonl
│ ├── tools/
│ └── history/
│
└── resources/{project}/ # Resource workspace
viking://resources/ # All resources
viking://resources/my-project/ # Project root
viking://resources/my-project/docs/ # Docs directory
viking://resources/my-project/docs/api.md # Specific file
viking://user/ # User root
viking://user/memories/ # All user memories
viking://user/memories/preferences/ # User preferences
viking://user/memories/preferences/coding # Specific preference
viking://user/memories/entities/ # Entity memories
viking://user/memories/events/ # Event memories
viking://user/resources/ # Current user's resources
viking://user/resources/docs/ # Current user's resource directory
viking://user/skills/ # Current user's skills
viking://user/skills/search-web # Specific skill
viking://user/memories/ # Current user's memories
viking://user/memories/cases/ # Learned cases
viking://user/memories/patterns/ # Learned patterns
viking://user/{user_id}/peers/{peer_id}/memories/
viking://user/{user_id}/peers/{peer_id}/resources/
The short viking://user/... form is relative to the current request identity.
OpenViking expands it internally to explicit namespace paths such as
viking://user/{user_id}/... before storage and retrieval.
Identity path segments such as {user_id} and {peer_id} must be safe single
segments, for example alice or web-visitor-alice.
viking://user/{user_id}/sessions/{session_id}/ # Session root
viking://user/{user_id}/sessions/{session_id}/messages # Session messages
viking://user/{user_id}/sessions/{session_id}/tools # Tool executions
viking://user/{user_id}/sessions/{session_id}/history # Archived history
viking://user/sessions/{session_id}/ # Current-user short form
viking://session/{session_id} is accepted as a backward-compatible alias for
the current user's session path. It is not a separate storage root for new
session data.
Viking URI supports path variables for dynamic path generation. This is especially useful for organizing time-series data like emails, logs, daily reports, etc.
{namespace:key}
calendar, env, user)The calendar namespace provides date-related variables:
| Variable | Description | Example (2026-05-07) |
|---|---|---|
{calendar:today} | Full date path | 2026/05/07 |
{calendar:yesterday} | Yesterday's date path | 2026/05/06 |
{calendar:tomorrow} | Tomorrow's date path | 2026/05/08 |
{calendar:year} | Year | 2026 |
{calendar:month} | Month with leading zero | 05 |
{calendar:day} | Day with leading zero | 07 |
{calendar:ym} | Year/month | 2026/05 |
{calendar:quarter} | Quarter (Q1-Q4) | Q2 |
{calendar:yq} | Year/quarter | 2026/Q2 |
{calendar:week} | ISO week number with leading zero | 18 |
{calendar:yw} | Year/ISO week | 2026/w18 |
# Organize emails by date
viking://resources/emails/{calendar:today}/inbox
# Renders to: viking://resources/emails/2026/05/07/inbox
# View yesterday's logs
viking://resources/logs/{calendar:yesterday}/app.log
# Renders to: viking://resources/logs/2026/05/06/app.log
# Pre-upload tomorrow's tasks
viking://resources/tasks/{calendar:tomorrow}/todo.md
# Renders to: viking://resources/tasks/2026/05/08/todo.md
# Monthly logs
viking://resources/logs/{calendar:year}/{calendar:month}/app.log
# Renders to: viking://resources/logs/2026/05/app.log
# Daily snapshots
viking://resources/snapshots/{calendar:today}/
# Renders to: viking://resources/snapshots/2026/05/07/
Path variables are resolved server-side at the time of API execution. The CLI/SDK passes the URI template as-is, and the server renders it to a concrete path based on the current context (time, authenticated user, etc.).
# Add today's emails, --parent-auto-create can be shortened to -p
ov add-resource --parent-auto-create "viking://resources/emails/{calendar:today}/inbox" ./emails/*.eml
# Read yesterday's log
ov read "viking://resources/logs/{calendar:yesterday}/app.log"
# Prep tomorrow's tasks
ov write --uri "viking://resources/tasks/{calendar:tomorrow}/todo.md" --content "Plan the day"
# Upload monthly report, --parent-auto-create can be shortened to -p
ov add-resource --parent-auto-create "viking://resources/reports/{calendar:ym}" ./report.pdf
viking://
├── resources/ # Independent resources
│ └── {project}/
│ ├── .abstract.md
│ ├── .overview.md
│ └── {files...}
│
├── user/{user_id}/
│ ├── profile.md # User basic info
│ ├── memories/
│ │ ├── preferences/ # By topic
│ │ ├── entities/ # Each independent
│ │ └── events/ # Each independent
│ ├── resources/
│ │ └── {project}/
│ ├── skills/
│ └── peers/{peer_id}/
│ ├── memories/
│ └── resources/
│
└── user/{user_id}/sessions/{session_id}/
├── messages.jsonl
├── tools/
└── history/
viking://agent/... is deprecated and only kept for read-only legacy agent
compatibility. New data should be written under
viking://user/{user_id}/peers/{peer_id}/....
from openviking_cli.utils.uri import VikingURI
uri = VikingURI("viking://resources/docs/api")
print(uri.scope) # "resources"
print(uri.full_path) # "resources/docs/api"
# Join paths
base = "viking://resources/docs/"
full = VikingURI(base).join("api.md").uri # viking://resources/docs/api.md
# Parent directory
uri = "viking://resources/docs/api.md"
parent = VikingURI(uri).parent.uri # viking://resources/docs
# Search only in resources
results = client.find(
"authentication",
target_uri="viking://resources/"
)
# Search only in current-user resources
results = client.find(
"private project notes",
target_uri="viking://user/resources/"
)
# Search only in user memories
results = client.find(
"coding preferences",
target_uri="viking://user/memories/"
)
# Search only in skills
results = client.find(
"web search",
target_uri="viking://user/skills/"
)
# List directory
entries = await client.ls("viking://resources/")
# Read file
content = await client.read("viking://resources/docs/api.md")
# Get abstract
abstract = await client.abstract("viking://resources/docs/")
# Get overview
overview = await client.overview("viking://resources/docs/")
Each directory may contain special files:
| File | Purpose |
|---|---|
.abstract.md | L0 abstract (~100 tokens) |
.overview.md | L1 overview (~2k tokens) |
.relations.json | Related resources |
.meta.json | Metadata |
# Directory
"viking://resources/docs/"
# File
"viking://resources/docs/api.md"
# Add resources to the shared account resource scope
await client.add_resource(url, to="viking://resources/project/")
# Add private resources to the current user's resource root
await client.add_resource(path, parent="viking://user/resources/project/")
# Skills always go to the current user's skills root
await client.add_skill(skill) # Canonical root: viking://user/{user_id}/skills/