How to Manage Resources Using the viking:// URI Protocol in OpenViking
OpenViking uses the viking:// URI scheme to uniquely identify every object in the system, with the VikingURI class in openviking_cli/utils/uri.py providing parsing, validation, normalization, and composition utilities that serve as the single source of truth for resource management across the SDK.
The OpenViking SDK from Volcengine implements a unified resource addressing system through the viking:// URI protocol. Every file, directory, semantic node, queue, and session receives a unique identifier following the viking://<scope>/<path> format. The VikingURI class serves as the central abstraction for managing these identifiers, ensuring consistent validation and manipulation across the HTTP client, storage layer, and file system wrappers.
Understanding the viking:// URI Structure
OpenViking identifies every object with a Viking URI following the strict format:
viking://<scope>/<path>
The scope component defines the namespace and must be one of the predefined values: resources, user, agent, session, queue, or temp. The remainder of the path varies by scope type, representing project names, file hierarchies, or unique identifiers depending on the resource category.
Core URI Operations with VikingURI
The VikingURI class in openviking_cli/utils/uri.py implements the complete lifecycle of URI handling. According to the OpenViking source code, this class provides immutable, hashable objects that normalize input, validate scope constraints, and enable hierarchical navigation.
Normalization and Validation
The normalize() class method guarantees the viking:// scheme even when callers provide short-form strings such as /resources/docs or bare paths like resources/docs. The is_valid() method returns True only for syntactically correct URIs with approved scope values, as validated against the internal VALID_SCOPES constant.
Parsing and Scope Inspection
The internal _parse() method splits a full URI into scheme, scope, and full_path components. For resources scope URIs, the resource_name property extracts the project name, while the parent property walks one level up the hierarchy to return a new VikingURI instance.
URI Composition and Building
The build() class method constructs URIs from a scope and arbitrary path parts, while join() appends new segments handling slash normalization automatically. For semantic node creation, build_semantic_uri() creates hierarchical paths with optional node IDs for leaf nodes.
Temporary Workspace Generation
The create_temp_uri() method generates unique viking://temp/... paths for short-lived workspaces, returning fully validated VikingURI instances ready for immediate use.
Practical Resource Management Examples
The following examples demonstrate common patterns for managing resources using the viking:// URI protocol.
Normalizing Short-Form URIs
from openviking_cli.utils import VikingURI
# Short-form input automatically becomes full-form
uri = VikingURI("/resources/docs")
print(uri.uri) # → viking://resources/docs
# Normalizing an already-full URI is a no-op
print(VikingURI.normalize("viking://user/profile")) # → viking://user/profile
Validating Resource Identifiers
# Validate a URI string
assert VikingURI.is_valid("viking://agent/skills/pdf")
# Invalid scope raises at construction time
try:
VikingURI("viking://invalid_scope/foo")
except ValueError as e:
print(e) # → Invalid scope 'invalid_scope'. Must be one of {...}
Constructing Hierarchical Paths
# Build a URI from a scope and arbitrary path parts
full_uri = VikingURI.build("resources", "my_project", "docs", "api")
print(full_uri) # → viking://resources/my_project/docs/api
# Join a new segment to an existing URI
uri = VikingURI("viking://resources/my_project")
new_uri = uri.join("readme.md")
print(new_uri.uri) # → viking://resources/my_project/readme.md
Navigating Parent Directories
uri = VikingURI("viking://resources/my_project/docs/api")
print(uri.parent.uri) # → viking://resources/my_project/docs
print(uri.resource_name) # → my_project
Creating Semantic Nodes
parent = "viking://resources/my_project"
semantic = VikingURI.build_semantic_uri(parent, "Chapter 1")
print(semantic) # → viking://resources/my_project/Chapter_1
# Leaf node with explicit ID
leaf = VikingURI.build_semantic_uri(parent, "Section A", node_id="12345", is_leaf=True)
print(leaf) # → viking://resources/my_project/Section_A/12345
Generating Temporary Workspaces
tmp_uri = VikingURI.create_temp_uri()
print(tmp_uri) # → viking://temp/03291530_1a2b3c (example)
Integration with OpenViking Components
Higher-level components rely on VikingURI primitives, creating a single source of truth for URI handling across the codebase.
HTTP Client Normalization
The HTTP client in openviking_cli/client/http.py normalizes every incoming user-provided string before sending it to the backend:
uri = VikingURI.normalize(uri) # https://github.com/volcengine/OpenViking/blob/main/openviking_cli/client/http.py#L95-L98
Storage Layer Operations
The file-system wrapper in openviking/storage/viking_fs.py uses VikingURI for parent resolution, resource-name extraction, and validation when interacting with the underlying AGFS storage:
parent_uri = VikingURI(uri).parent.uri # https://github.com/volcengine/OpenViking/blob/main/openviking/storage/viking_fs.py#L891
Test Coverage
Unit tests in tests/unit/test_uri_short_format.py verify short-format normalization, validation, parent resolution, and scope handling, while integration tests across tests/vectordb/ and tests/storage/ exercise VikingURI in real-world scenarios.
Summary
- OpenViking addresses all resources using the
viking://<scope>/<path>format with six valid scopes:resources,user,agent,session,queue, andtemp. - The
VikingURIclass inopenviking_cli/utils/uri.pyprovides immutable, hashable objects supporting normalization, validation, composition, and hierarchical navigation. normalize()ensures consistentviking://prefixes whilebuild(),join(), andbuild_semantic_uri()enable programmatic URI construction for theviking://URI protocol.- Integration points in
openviking_cli/client/http.pyandopenviking/storage/viking_fs.pydemonstrate the class role as the bridge between user-facing strings and internal storage APIs.
Frequently Asked Questions
What are the valid scope types for viking:// URIs?
OpenViking recognizes six predefined scopes: resources for project files and data, user for user-specific data, agent for agent configurations and skills, session for session state, queue for task queues, and temp for temporary workspaces. The VikingURI class validates all scopes against the VALID_SCOPES constant in openviking_cli/utils/uri.py, raising ValueError for any invalid scope identifier.
How does VikingURI handle short-form URI strings?
The normalize() method automatically converts short-form inputs like /resources/docs or bare resources/docs into full viking://resources/docs format. This normalization occurs at construction time and throughout the SDK, ensuring the HTTP client and storage layer always receive properly formatted URIs regardless of user input style.
Can VikingURI objects be used as dictionary keys?
Yes. The VikingURI class implements __eq__ and __hash__ methods, making instances immutable and hashable. This design allows URIs to serve as keys in dictionaries or elements in sets, enabling efficient lookup and deduplication of resource identifiers across the OpenViking codebase.
How do I create a temporary workspace URI in OpenViking?
Call VikingURI.create_temp_uri() to generate a unique temporary URI under the viking://temp/ scope. This method returns a fully validated VikingURI instance with a generated path segment suitable for short-lived workspaces, as implemented in openviking_cli/utils/uri.py.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →