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
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, and temp.
  • The VikingURI class in openviking_cli/utils/uri.py provides immutable, hashable objects supporting normalization, validation, composition, and hierarchical navigation.
  • normalize() ensures consistent viking:// prefixes while build(), join(), and build_semantic_uri() enable programmatic URI construction for the viking:// URI protocol.
  • Integration points in openviking_cli/client/http.py and openviking/storage/viking_fs.py demonstrate 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →