Skip to content

Sessions ​

Sessions manage conversation state, track context usage, and extract long-term memories. Sessions use tiered storage (L0/L1/L2) to optimize token usage:

  • L0 (abstract): Session overview summary
  • L1 (overview): Key decisions
  • L2 (messages): Complete messages

Sessions are stored under the current user's namespace:

text
viking://user/{user_id}/sessions/{session_id}

Session APIs are scoped to the authenticated user and return canonical user session URIs. URI-based APIs may also accept the backward-compatible viking://session/{session_id} alias, resolved in the same user context.

API Reference ​

create_session() ​

1. API Implementation Introduction ​

Create a new session. Sessions are containers for conversations, storing messages, tracking context usage, and supporting commits for long-term memory extraction.

Processing Flow:

  1. Generate or use provided session_id
  2. Initialize session metadata (creation time, user info, etc.)
  3. Create session directory structure in storage
  4. Return session info

Code Entries:

  • openviking/session/session.py:Session.__init__() - Core Session class
  • openviking/session/auto_commit_policy.py:AutoCommitPolicy - Auto-commit policy defaults and validation
  • openviking/server/routers/sessions.py:create_session() - HTTP route
  • sdk/python/openviking_sdk/client.py:AsyncHTTPClient.create_session() - Python SDK
  • crates/ov_cli/src/commands/session.rs:new_session() - CLI command

2. Interface and Parameter Description ​

Parameters

ParameterTypeRequiredDefaultDescription
session_idstrNoNoneSession ID. Creates new session with auto-generated ID if None
memory_policyobjectNoNoneDefault memory extraction policy for the session. Optional self and peer switches control write targets, working_memory.enabled defaults to false (no archive/checkpoint summaries); explicitly set it to true to generate summaries, and optional top-level memory_types limits extraction to specific enabled memory schemas. Including experiences automatically activates cases and trajectories; without experiences, explicitly supplied cases and trajectories are ignored. Use JSON booleans for every enabled value. Legacy boolean-like values remain accepted temporarily (including string "false", which is parsed as false) but emit a deprecation warning. When memory_types is omitted or null, all enabled memory schemas are allowed. Invalid shapes or unknown memory types are rejected with InvalidArgumentError.
auto_commit_policyobjectNoNoneOptional auto-commit policy (see table below). Any provided fields are validated, clamped to their bounds, and merged over the defaults; the effective policy is returned in the response result.auto_commit_policy and persisted into session metadata. If omitted, the new Session inherits server.user_config_defaults.auto_commit_policy, then the existing memory.session_auto_commit.enabled behavior. The policy can later be partially updated or disabled through update_session_config().

auto_commit_policy fields (all optional; omitted fields fall back to the defaults when a policy is present):

FieldTypeDefaultMinMaxDescription
pending_token_thresholdint15000001000000When uncommitted pending tokens exceed this value (strictly greater-than), an auto commit is triggered after a message write.
message_count_thresholdint10001000When the uncommitted live message count exceeds this value (strictly greater-than), an auto commit is triggered after a message write.
idle_timeout_secondsint864000 (off) or 300604800After this many idle seconds, a session with uncommitted content becomes eligible for the server-side idle scheduler. An idle-timeout commit archives the full backlog and ignores keep_recent_count.
keep_recent_countint00500Number of recent live messages to keep (not archived) on a threshold-triggered auto commit. Idle-timeout commits ignore this and commit everything.
min_commit_interval_secondsint00604800Minimum seconds between two automatic commits (throttle).

New idle_timeout_seconds inputs must be 0 (off) or at least 300; values above 604800 are clamped to that maximum. For stored-data compatibility, existing positive values below 300 continue to be read unchanged. Other fields have a minimum of 0 and are clamped to their ranges. Unknown keys are rejected with InvalidArgumentError. Idle commits also require memory.session_auto_commit.enabled on the server; setting idle_timeout_seconds alone does not start the scanner.

3. Usage Examples ​

HTTP API

http
POST /api/v1/sessions
bash
# Create new session (auto-generated ID)
curl -X POST http://localhost:1933/api/v1/sessions \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key"

# Create new session with specified ID
curl -X POST http://localhost:1933/api/v1/sessions \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{"session_id": "my-custom-session-id"}'

# Create new session with a custom auto-commit policy
curl -X POST http://localhost:1933/api/v1/sessions \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "auto_commit_policy": {
      "pending_token_threshold": 8000,
      "message_count_threshold": 40,
      "idle_timeout_seconds": 600,
      "keep_recent_count": 10,
      "min_commit_interval_seconds": 0
    }
  }'

Python SDK

python
import openviking_sdk as ov

# Use HTTP client
client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

# Create new session (auto-generated ID)
result = client.create_session()
print(f"Session ID: {result['session_id']}")

# Create new session with specified ID
result = client.create_session(session_id="my-custom-session-id")
print(f"Session ID: {result['session_id']}")

# Create new session with a custom auto-commit policy
result = client.create_session(
    options={
        "auto_commit_policy": {
            "pending_token_threshold": 8000,
            "message_count_threshold": 40,
            "idle_timeout_seconds": 600,
            "keep_recent_count": 10,
            "min_commit_interval_seconds": 0,
        },
    },
)
print(result["auto_commit_policy"])

TypeScript SDK

typescript
const session = await client.createSession();
console.log(session);

Go SDK

go
session, err := client.CreateSession(ctx, &openviking.CreateSessionOptions{
    SessionID: "my-custom-session-id",
})
if err != nil {
    return err
}
fmt.Println(session["session_id"])

CLI

bash
ov session new

Response Example

json
{
  "status": "ok",
  "result": {
    "session_id": "a1b2c3d4",
    "uri": "viking://user/alice/sessions/a1b2c3d4",
    "user": {
      "account_id": "default",
      "user_id": "alice"
    },
    "auto_commit_policy": null
  }
}

list_sessions() ​

1. API Implementation Introduction ​

List all sessions for the current user. Returns session IDs and URI info for further operations.

Code Entries:

  • openviking/server/routers/sessions.py:list_sessions() - HTTP route
  • sdk/python/openviking_sdk/client.py:AsyncHTTPClient.list_sessions() - Python SDK
  • crates/ov_cli/src/commands/session.rs:list_sessions() - CLI command

2. Interface and Parameter Description ​

Parameters

None.

3. Usage Examples ​

HTTP API

http
GET /api/v1/sessions
bash
curl -X GET http://localhost:1933/api/v1/sessions \
  -H "X-API-Key: your-key"

Python SDK

python
from openviking_sdk import SyncHTTPClient

client = SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

sessions = client.list_sessions()
for s in sessions:
    print(f"{s['session_id']} -> {s['uri']}")

TypeScript SDK

typescript
console.log(await client.listSessions());

Go SDK

go
sessions, err := client.ListSessions(ctx)
if err != nil {
    return err
}
for _, session := range sessions {
    fmt.Println(session)
}

CLI

bash
ov session list

Response Example

json
{
  "status": "ok",
  "result": [
    {
      "session_id": "a1b2c3d4",
      "uri": "viking://user/alice/sessions/a1b2c3d4",
      "is_dir": true
    },
    {
      "session_id": "e5f6g7h8",
      "uri": "viking://user/alice/sessions/e5f6g7h8",
      "is_dir": true
    }
  ]
}

get_session() ​

1. API Implementation Introduction ​

Get session details including metadata, message statistics, commit history, etc. Supports auto-creating sessions when they don't exist.

Return Fields Description:

  • message_count: Number of current live, unarchived messages
  • total_message_count: Cumulative count of archived and current live messages (older sessions may omit this field)
  • commit_count: Number of successful commits
  • memories_extracted: Count statistics of extracted memories by category
  • last_commit_at: Time of last commit
  • auto_commit_policy: Effective auto-commit policy with defaults filled in; null when not enabled

Code Entries:

  • openviking/session/session.py:Session.load() - Session loading
  • openviking/server/routers/sessions.py:get_session() - HTTP route
  • sdk/python/openviking_sdk/client.py:AsyncHTTPClient.get_session() - Python SDK
  • crates/ov_cli/src/commands/session.rs:get_session() - CLI command

2. Interface and Parameter Description ​

Parameters

ParameterTypeRequiredDefaultDescription
session_idstrYes-Session ID
auto_createboolNoFalseWhether to auto-create the session if it does not exist

3. Usage Examples ​

HTTP API

http
GET /api/v1/sessions/{session_id}?auto_create=false
bash
curl -X GET http://localhost:1933/api/v1/sessions/a1b2c3d4 \
  -H "X-API-Key: your-key"

Python SDK

python
from openviking_sdk import SyncHTTPClient

client = SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

# Get existing session (raises NotFoundError if not found)
info = client.get_session(session_id="a1b2c3d4")
print(f"Live Messages: {info['message_count']}")
print(f"Total Messages: {info.get('total_message_count', 'n/a')}")
print(f"Commits: {info['commit_count']}")

# Get or create session
info = client.get_session(session_id="a1b2c3d4", auto_create=True)

TypeScript SDK

typescript
console.log(await client.getSession("session-id"));

Go SDK

go
// Get an existing session.
info, err := client.GetSession(ctx, "a1b2c3d4", nil)
if err != nil {
    return err
}
fmt.Println(info["message_count"])

// Get or create session.
info, err = client.GetSession(ctx, "a1b2c3d4", &openviking.GetSessionOptions{
    AutoCreate: true,
})
if err != nil {
    return err
}
fmt.Println(info["session_id"])

CLI

bash
ov session get a1b2c3d4

Response Example

json
{
  "status": "ok",
  "result": {
    "session_id": "a1b2c3d4",
    "created_at": "2026-03-23T10:00:00+08:00",
    "updated_at": "2026-03-23T11:30:00+08:00",
    "message_count": 5,
    "total_message_count": 20,
    "commit_count": 3,
    "memories_extracted": {
      "profile": 1,
      "preferences": 2,
      "entities": 3,
      "events": 1,
      "identity": 1,
      "soul": 1,
      "cases": 2,
      "trajectories": 1,
      "experiences": 2,
      "tools": 0,
      "skills": 0,
      "total": 14
    },
    "last_commit_at": "2026-03-23T11:00:00+08:00",
    "llm_token_usage": {
      "prompt_tokens": 5200,
      "completion_tokens": 1800,
      "total_tokens": 7000,
      "cached_tokens": 1200,
      "reasoning_tokens": 800
    },
    "user": {
      "account_id": "default",
      "user_id": "alice"
    },
    "pending_tokens": 450,
    "auto_commit_policy": {
      "pending_token_threshold": 150000,
      "message_count_threshold": 100,
      "idle_timeout_seconds": 86400,
      "keep_recent_count": 0,
      "min_commit_interval_seconds": 0
    }
  }
}

update_session_config() ​

1. API Implementation Introduction ​

Partially update the mutable configuration of an existing session. Changes take effect on subsequent message writes, idle scans, and commits. Only the /api/v1/sessions/{session_id}/config subpath accepts PATCH; the base /api/v1/sessions/{session_id} endpoint does not.

Code Entry Points:

  • openviking/server/routers/sessions.py:update_session_config() - HTTP route
  • openviking/service/session_service.py:SessionService.update_config() - Config validation and update
  • sdk/python/openviking_sdk/client.py:update_session_config() - Python SDK
  • sdk/typescript/src/client.ts:updateSessionConfig() - TypeScript SDK
  • sdk/go/sessions.go:UpdateSessionConfig() - Go SDK
  • crates/ov_cli/src/commands/session.rs:set_session_config() - CLI command

2. Interface and Parameter Description ​

ParameterTypeRequiredDefaultDescription
session_idstringYes-Session ID in the URL path
memory_extraction_configobjectNoOmittedMutable extraction settings. Currently supports events.tags, an array of strict key=value strings. Omit it to preserve the current tags; pass events.tags=[] to clear them. Tags are trimmed, lowercased, and deduplicated.
auto_commit_policyobject or nullNoOmittedAn object merges only the supplied policy fields into the current policy, with the same validation, clamping, defaults, and bounds documented under create_session(). Pass null to disable automatic commits; omit the field to leave the policy unchanged. Individual policy fields cannot be null.
telemetryboolean or objectNofalseSet to true, or pass {"summary": true}, to include the operation telemetry summary in the response. false omits it.

An empty request object is a valid no-op and returns the effective configuration. Unknown request fields are rejected. The response always returns the effective policy with defaults filled in, or null when automatic commits are disabled.

3. Usage Examples ​

HTTP API

http
PATCH /api/v1/sessions/{session_id}/config
bash
# Merge one policy field and replace the default event-memory tags
curl -X PATCH http://localhost:1933/api/v1/sessions/a1b2c3d4/config \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "memory_extraction_config": {
      "events": {"tags": ["team=search", "channel=app"]}
    },
    "auto_commit_policy": {"message_count_threshold": 25},
    "telemetry": true
  }'

# Disable automatic commits without changing event-memory tags
curl -X PATCH http://localhost:1933/api/v1/sessions/a1b2c3d4/config \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{"auto_commit_policy": null}'

Python SDK

python
result = client.update_session_config(
    session_id="a1b2c3d4",
    options={
        "memory_extraction_config": {
            "events": {"tags": ["team=search", "channel=app"]}
        },
        "auto_commit_policy": {"message_count_threshold": 25},
    },
)

TypeScript SDK

typescript
const result = await client.updateSessionConfig("a1b2c3d4", {
  memoryExtractionConfig: {
    events: { tags: ["team=search", "channel=app"] },
  },
  autoCommitPolicy: { message_count_threshold: 25 },
});

Go SDK

go
policy := map[string]any{"message_count_threshold": 25}
result, err := client.UpdateSessionConfig(ctx, "a1b2c3d4", &openviking.UpdateSessionConfigOptions{
    MemoryExtractionConfig: map[string]any{
        "events": map[string]any{"tags": []string{"team=search", "channel=app"}},
    },
    AutoCommitPolicy: &policy,
})

CLI

bash
ov session config set a1b2c3d4 \
  --event-tags team=search,channel=app \
  --auto-commit-policy-json '{"message_count_threshold":25}'

# Clear the default tags, or disable automatic commits
ov session config set a1b2c3d4 --no-event-tags
ov session config set a1b2c3d4 --no-auto-commit

Response example

json
{
  "status": "ok",
  "result": {
    "session_id": "a1b2c3d4",
    "auto_commit_policy": {
      "pending_token_threshold": 150000,
      "message_count_threshold": 25,
      "idle_timeout_seconds": 86400,
      "keep_recent_count": 0,
      "min_commit_interval_seconds": 0
    },
    "memory_extraction_config": {
      "events": {
        "tags": ["team=search", "channel=app"]
      }
    }
  },
  "telemetry": {
    "id": "tm_xxx",
    "summary": {
      "operation": "session.update_config",
      "status": "ok",
      "duration_ms": 4.2
    }
  }
}

list_tool_results() ​

List large tool results externalized from a session.

ParameterTypeRequiredDefaultDescription
session_idstringYes-Session ID
tool_namestringNo-Filter by tool name
limitintegerNo50Maximum results

HTTP API

http
GET /api/v1/sessions/{session_id}/tool-results
bash
curl --get http://localhost:1933/api/v1/sessions/session-id/tool-results \
  -H "X-API-Key: your-key" \
  --data-urlencode "tool_name=search" \
  --data-urlencode "limit=50"

Response example

json
{
  "status": "ok",
  "result": {
    "tool_results": [
      {
        "tool_result_id": "tr_search_a1b2c3",
        "tool_name": "search",
        "original_chars": 48210,
        "preview_chars": 2000,
        "mime_type": "text/plain",
        "synopsis_kind": "text",
        "storage_uri": "viking://user/default/sessions/session-id/tool-results/tr_search_a1b2c3",
        "offset_unit": "unicode_code_point"
      }
    ]
  }
}

read_tool_result() ​

Read one externalized tool result by Unicode character range.

ParameterTypeRequiredDefaultDescription
session_idstringYes-Session ID
tool_result_idstringYes-Tool-result ID
offsetintegerNo0Starting character offset
limitintegerNo20000Maximum characters; -1 reads to the end
include_metadatabooleanNotrueInclude metadata in the response

HTTP API

http
GET /api/v1/sessions/{session_id}/tool-results/{tool_result_id}
bash
curl --get http://localhost:1933/api/v1/sessions/session-id/tool-results/tool-result-id \
  -H "X-API-Key: your-key" \
  --data-urlencode "offset=0" \
  --data-urlencode "limit=20000"

Response example

json
{
  "status": "ok",
  "result": {
    "tool_result_id": "tr_search_a1b2c3",
    "content": "A chunk of the tool output...",
    "offset": 0,
    "limit": 20000,
    "offset_unit": "unicode_code_point",
    "total_chars": 48210,
    "has_more": true,
    "metadata": {
      "tool_name": "search",
      "mime_type": "text/plain",
      "sha256": "..."
    }
  }
}

metadata is omitted when include_metadata=false. To continue reading, set the next request's offset to the current offset plus the Unicode character count of content.

search_tool_result() ​

Search within one externalized tool result and return context around each match.

ParameterTypeRequiredDefaultDescription
qstringYes-Search text
limitintegerNo20Maximum matches
context_charsintegerNo300Context characters around each match

HTTP API

http
GET /api/v1/sessions/{session_id}/tool-results/{tool_result_id}/search?q={query}
bash
curl --get http://localhost:1933/api/v1/sessions/session-id/tool-results/tool-result-id/search \
  -H "X-API-Key: your-key" \
  --data-urlencode "q=authentication" \
  --data-urlencode "limit=20"

Response example

json
{
  "status": "ok",
  "result": {
    "tool_result_id": "tr_search_a1b2c3",
    "matches": [
      {
        "offset": 1284,
        "offset_unit": "unicode_code_point",
        "snippet": "...authentication failed because..."
      }
    ]
  }
}

These endpoints are currently used by the Server and Web Studio. The public SDKs and CLI do not wrap them, so the sections above show only the HTTP tab.


get_session_context() ​

1. API Implementation Introduction ​

Get the assembled session context used for LLM context building. This endpoint returns the latest archive overview and current live messages.

Return Fields Description:

  • latest_archive_overview: The overview of the latest completed archive, when it fits the token budget
  • pre_archive_abstracts: Kept for backward compatibility, returns empty array
  • messages: Incomplete archive messages after the latest completed archive and current live messages, limited to the token budget
  • estimatedTokens: Estimated total tokens
  • stats: Statistics. includedArchives counts entries in pre_archive_abstracts, which is currently empty; check latest_archive_overview itself to see whether an overview is included

Token Budget Allocation Strategy:

  1. Fit the messages into the budget first, dropping or truncating messages when needed, then calculate the remaining budget
  2. Remaining budget prioritizes the latest archive overview
  3. Pre-archive abstracts are not currently returned

Code Entries:

  • openviking/session/session.py:Session.get_session_context() - Core implementation
  • openviking/server/routers/sessions.py:get_session_context() - HTTP route
  • sdk/python/openviking_sdk/client.py:AsyncHTTPClient.get_session_context() - Python SDK
  • crates/ov_cli/src/commands/session.rs:get_session_context() - CLI command

2. Interface and Parameter Description ​

Parameters

ParameterTypeRequiredDefaultDescription
session_idstrYes-Session ID
token_budgetintNo128000Non-negative budget for the entire returned context; messages are budgeted first, then the archive overview uses the remainder

3. Usage Examples ​

HTTP API

http
GET /api/v1/sessions/{session_id}/context?token_budget=128000
bash
curl -X GET "http://localhost:1933/api/v1/sessions/a1b2c3d4/context?token_budget=128000" \
  -H "X-API-Key: your-key"

Python SDK

python
from openviking_sdk import SyncHTTPClient

client = SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

context = client.get_session_context(session_id="a1b2c3d4", token_budget=128000)
print(context["latest_archive_overview"])
print(len(context["messages"]))

TypeScript SDK

typescript
console.log(await client.getSessionContext("session-id"));

Go SDK

go
contextPayload, err := client.GetSessionContext(ctx, "a1b2c3d4", 128000)
if err != nil {
    return err
}
fmt.Println(contextPayload["latest_archive_overview"])

CLI

bash
ov session get-session-context a1b2c3d4 --token-budget 128000

Response Example

json
{
  "status": "ok",
  "result": {
    "latest_archive_overview": "# Session Summary\n\n**Overview**: User discussed deployment and auth setup.",
    "pre_archive_abstracts": [],
    "messages": [
      {
        "id": "msg_pending_1",
        "role": "user",
        "parts": [
          {"type": "text", "text": "Pending user message"}
        ],
        "created_at": "2026-03-24T09:10:11Z"
      },
      {
        "id": "msg_live_1",
        "role": "assistant",
        "parts": [
          {"type": "text", "text": "Current live message"}
        ],
        "created_at": "2026-03-24T09:10:20Z"
      }
    ],
    "estimatedTokens": 29,
    "stats": {
      "totalArchives": 2,
      "includedArchives": 0,
      "droppedArchives": 2,
      "failedArchives": 0,
      "activeTokens": 10,
      "archiveTokens": 19
    }
  }
}

get_session_archive() ​

1. API Implementation Introduction ​

Get the full contents of one completed archive for a session. A normal WM-disabled archive returns its raw messages with empty abstract and overview; no summary is generated on read. Pending, failed, missing, or corrupt archives retain their existing error behavior. This explicit history read is independent of the bounded get_session_context() prompt view.

Code Entries:

  • openviking/session/session.py:Session.get_session_archive() - Core implementation
  • openviking/server/routers/sessions.py:get_session_archive() - HTTP route
  • sdk/python/openviking_sdk/client.py:AsyncHTTPClient.get_session_archive() - Python SDK
  • crates/ov_cli/src/commands/session.rs:get_session_archive() - CLI command

2. Interface and Parameter Description ​

Parameters

ParameterTypeRequiredDefaultDescription
session_idstrYes-Session ID
archive_idstrYes-Archive ID such as archive_002

3. Usage Examples ​

HTTP API

http
GET /api/v1/sessions/{session_id}/archives/{archive_id}
bash
curl -X GET "http://localhost:1933/api/v1/sessions/a1b2c3d4/archives/archive_002" \
  -H "X-API-Key: your-key"

Python SDK

python
import openviking_sdk as ov

client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

archive = client.get_session_archive(
    session_id="a1b2c3d4",
    archive_id="archive_002",
)
print(archive["archive_id"])
print(archive["overview"])
print(len(archive["messages"]))

TypeScript SDK

typescript
console.log(await client.getSessionArchive("session-id", "archive-id"));

Go SDK

go
archive, err := client.GetSessionArchive(ctx, "a1b2c3d4", "archive_002")
if err != nil {
    return err
}
fmt.Println(archive["archive_id"])

CLI

bash
ov session get-session-archive a1b2c3d4 archive_002

Response Example

json
{
  "status": "ok",
  "result": {
    "archive_id": "archive_002",
    "abstract": "User discussed deployment and authentication setup.",
    "overview": "# Session Summary\n\n**Overview**: User discussed deployment and auth setup.",
    "messages": [
      {
        "id": "msg_archive_1",
        "role": "user",
        "parts": [
          {"type": "text", "text": "How should I deploy this service?"}
        ],
        "created_at": "2026-03-24T08:55:01Z"
      },
      {
        "id": "msg_archive_2",
        "role": "assistant",
        "parts": [
          {"type": "text", "text": "Use the staged deployment flow and verify auth first."}
        ],
        "created_at": "2026-03-24T08:55:18Z"
      }
    ]
  }
}

Error Response

If the archive does not exist, is incomplete, or does not belong to the session, the API returns 404:

json
{
  "status": "error",
  "error": {
    "code": "NOT_FOUND",
    "message": "Archive archive_002 not found"
  }
}

delete_session() ​

1. API Implementation Introduction ​

Delete the session directory, including messages, archives, and session audit records. Long-term memories already extracted into user or Peer memory directories remain; locate and delete those URIs separately when needed. This endpoint has no automatic undo.

Code Entries:

  • openviking/server/routers/sessions.py:delete_session() - HTTP route
  • sdk/python/openviking_sdk/client.py:AsyncHTTPClient.delete_session() - Python SDK
  • crates/ov_cli/src/commands/session.rs:delete_session() - CLI command

2. Interface and Parameter Description ​

Parameters

ParameterTypeRequiredDefaultDescription
session_idstrYes-Session ID to delete

3. Usage Examples ​

HTTP API

http
DELETE /api/v1/sessions/{session_id}
bash
curl -X DELETE http://localhost:1933/api/v1/sessions/a1b2c3d4 \
  -H "X-API-Key: your-key"

Python SDK

python
import openviking_sdk as ov

client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

# Delete session
client.delete_session(session_id="a1b2c3d4")

TypeScript SDK

typescript
await client.deleteSession("session-id");

Go SDK

go
if err := client.DeleteSession(ctx, "a1b2c3d4"); err != nil {
    return err
}

CLI

bash
ov session delete a1b2c3d4

Response Example

json
{
  "status": "ok",
  "result": {
    "session_id": "a1b2c3d4"
  }
}

add_message() ​

1. API Implementation Introduction ​

Add a message to the session. Supports two modes: simple text mode and Parts mode (supporting text, image URLs, context references, tool calls, etc.).

Part Types:

  • TextPart: Pure text content
  • ImagePart: OpenAI-style image URL content. During memory extraction, OpenViking can use the configured VLM to turn images into text descriptions.
  • ContextPart: Context reference pointing to resources or memories
  • ToolPart: Tool call and result

Code Entries:

  • openviking/session/session.py:Session.add_message() - Core implementation
  • openviking/server/routers/sessions.py:add_message() - HTTP route
  • sdk/python/openviking_sdk/client.py:AsyncHTTPClient.add_message() - Python SDK
  • crates/ov_cli/src/commands/session.rs:add_message() - CLI command

2. Interface and Parameter Description ​

Parameters

ParameterTypeRequiredDefaultDescription
session_idstrYes-Session ID
rolestrYes-Message role: "user" or "assistant"
partsList[dict | MessagePart]Conditional-SDK part dictionaries or TextPart/ContextPart/ImagePart/ToolPart objects; HTTP API accepts dictionaries only; use instead of content
contentstrConditional-Message text content (simple mode; use instead of parts)
peer_idstrNoNoneOptional stable interaction peer identity
optionsAddMessageOptionsNoNoneAdvanced message options such as created_at, telemetry, turn_id, message_kind, and source_message_ids

Note: HTTP API supports two modes:

  1. Simple mode: Use content string (backward compatible)
  2. Parts mode: Use parts array (full Part support)

If both content and parts are provided, parts takes precedence.

Part Types (Python SDK)

python
from openviking_sdk import ContextPart, ImagePart, TextPart, ToolPart

# Text content
TextPart(text="Hello, how can I help?")

# Image URL content
ImagePart(url="https://example.com/photo.png", detail="auto")

# Context reference
ContextPart(
    uri="viking://resources/docs/auth/",
    context_type="resource",  # "resource", "memory", or "skill"
    abstract="Authentication guide...",
)

# Tool call
ToolPart(
    tool_id="call_123",
    tool_name="search_web",
    skill_uri="viking://~/skills/search-web/",
    tool_input={"query": "OAuth best practices"},
    tool_status="pending",  # "pending", "running", "completed", "error"
)

You can also pass the equivalent dictionaries when you need to share the same payload shape with HTTP, Go, or TypeScript code.

3. Usage Examples ​

HTTP API

http
POST /api/v1/sessions/{session_id}/messages

Simple Mode (Backward Compatible)

bash
# Add user message
curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "role": "user",
    "content": "How do I authenticate users?"
  }'

Parts Mode (Full Part Support)

bash
# Add assistant message with context reference
curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "role": "assistant",
    "parts": [
      {"type": "text", "text": "Based on the authentication guide..."},
      {"type": "context", "uri": "viking://resources/docs/auth/", "context_type": "resource", "abstract": "Auth guide"}
    ]
  }'

# Add assistant message with tool call
curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "role": "assistant",
    "parts": [
      {"type": "text", "text": "Let me search for that..."},
      {"type": "tool", "tool_id": "call_123", "tool_name": "search_web", "tool_input": {"query": "OAuth"}, "tool_status": "completed", "tool_output": "Results..."}
    ]
  }'

# Add user message with an image URL
curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "role": "user",
    "parts": [
      {"type": "text", "text": "Remember this studio layout."},
      {"type": "image_url", "image_url": {"url": "https://example.com/studio.png", "detail": "auto"}}
    ]
  }'

Python SDK

python
import openviking_sdk as ov
from openviking_sdk import ContextPart, ImagePart, TextPart

client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

# Simple mode: Add user message
client.add_message(
    session_id="a1b2c3d4",
    role="user",
    content="How do I authenticate users?",
)

# Parts mode: Add assistant message with context reference
client.add_message(
    session_id="a1b2c3d4",
    role="assistant",
    parts=[
        TextPart(text="Based on the documentation, you can configure embedding..."),
        ContextPart(
            uri="viking://resources/docs/auth/",
            context_type="resource",
            abstract="Authentication guide",
        ),
    ],
)

# Parts mode: Add user message with an image URL
client.add_message(
    session_id="a1b2c3d4",
    role="user",
    parts=[
        TextPart(text="Remember this studio layout."),
        ImagePart(url="https://example.com/studio.png", detail="auto"),
    ],
)

TypeScript SDK

typescript
await client.addMessage("session-id", { role: "user", content: "Hello" });

Go SDK

go
result, err := client.AddMessage(ctx, "a1b2c3d4", "user", openviking.AddMessageOptions{
    Content: openviking.String("How do I authenticate users?"),
    PeerID:  "web-visitor-alice",
})
if err != nil {
    return err
}
fmt.Println(result["message_count"])

CLI

bash
ov session add-message a1b2c3d4 --role user --content "How do I authenticate users?"

Response Example

json
{
  "status": "ok",
  "result": {
    "session_id": "a1b2c3d4",
    "message_count": 2
  }
}

batch_add_messages() ​

1. API Implementation Introduction ​

Add multiple messages to a session in one request, for example when importing conversation history. Batching reduces the number of requests compared with calling add_message() for each message.

Difference from add_message():

  • add_message(): Add 1 message per request
  • batch_add_messages(): Add multiple messages per request (max 100), reducing network round trips and file I/O

Code Entry Points:

  • openviking/session/session.py:Session.add_messages() - Core implementation
  • openviking/server/routers/sessions.py:batch_add_messages() - HTTP route
  • sdk/python/openviking_sdk/client.py:AsyncHTTPClient.batch_add_messages() - Python SDK
  • crates/ov_cli/src/commands/session.rs:add_messages() - CLI command

2. Interface and Parameter Description ​

Parameters

ParameterTypeRequiredDefaultDescription
session_idstrYes-Session ID
messagesList[AddMessageRequest]Yes-List of messages, each following the same format as add_message(), max 100
optionsBatchAddMessagesOptionsNoNoneAdvanced batch options such as telemetry; pass options={"telemetry": True} to include operation telemetry data

Note: Each message follows the exact same format as add_message(), supporting both content (simple mode) and parts (Parts mode). If you need to add more than 100 messages, call in batches.

3. Usage Examples ​

HTTP API

http
POST /api/v1/sessions/{session_id}/messages/batch
bash
# Add multiple messages in batch
curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages/batch \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "messages": [
      {"role": "user", "content": "How do I authenticate users?"},
      {"role": "assistant", "content": "You can use OAuth 2.0 for authentication."},
      {"role": "user", "content": "Any specific recommendations?"}
    ]
  }'

Python SDK

python
from openviking_sdk import SyncHTTPClient

client = SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

# Add messages in batch
result = client.batch_add_messages(
    session_id="a1b2c3d4",
    messages=[
        {"role": "user", "content": "How do I authenticate users?"},
        {"role": "assistant", "content": "You can use OAuth 2.0 for authentication."},
        {"role": "user", "content": "Any specific recommendations?"},
    ],
)
print(f"Added: {result['added']}, Total: {result['message_count']}")

TypeScript SDK

typescript
await client.batchAddMessages("session-id", [
  { role: "user", content: "Hello" },
  { role: "assistant", content: "Hi" },
]);

Go SDK

go
result, err := client.BatchAddMessages(ctx, "a1b2c3d4", []openviking.Message{
    {Role: "user", Content: openviking.String("How do I authenticate users?")},
    {Role: "assistant", Content: openviking.String("You can use OAuth 2.0 for authentication.")},
    {Role: "user", Content: openviking.String("Any specific recommendations?")},
}, nil)
if err != nil {
    return err
}
fmt.Println(result["added"], result["message_count"])

CLI

bash
# Add multiple messages to a session
ov session add-messages a1b2c3d4 '[{"role":"user","content":"Hello"},{"role":"assistant","content":"Hi"}]'

# ov add-memory also uses the batch interface internally
ov add-memory '[{"role":"user","content":"Hello"},{"role":"assistant","content":"Hi"}]'

Response Example

json
{
  "status": "ok",
  "result": {
    "session_id": "a1b2c3d4",
    "message_count": 5,
    "added": 3
  }
}

commit() ​

1. API Implementation Introduction ​

Commit a session. Message archiving (Phase 1) completes before the response returns. Summary generation and memory extraction (Phase 2) run asynchronously in the background when messages are archived. Archived commits return status: "accepted" with a task_id; no-op commits return status: "skipped" with task_id: null.

The former standalone session extract endpoint has been removed. Use commit for memory extraction. This archives messages according to the retention policy; use the returned task_id to check the background extraction result. An accepted response does not mean extraction is complete.

Two-Phase Commit Flow:

  • Phase 1 (Synchronous): Split messages according to the retention policy, persist the archive and recovery records, enqueue Phase 2, and write retained messages back to the live session
  • Phase 2 (Asynchronous): Extract long-term memories; generate WM/checkpoint summaries only when the effective WM policy is enabled (default: disabled)

Notes:

  • Consecutive commits are accepted; only requests that produce an archive return a separate task_id. No-op commits do not create tasks.
  • Empty sessions, or commits where all messages remain inside keep_recent_count, complete synchronously with archived: false.
  • Background Phase 2 work is serialized by archive order: archive N+1 waits until archive N writes .done.
  • If an earlier archive failed and left no .done, later commit requests fail with FAILED_PRECONDITION until that failure is resolved.
  • If committed messages contain durable facts, judgments, preferences, or events that mention viking://resources/..., memory extraction preserves the resource as a markdown link and records it in MEMORY_FIELDS.resource_refs.

Code Entries:

  • openviking/session/session.py:Session.commit_async() - Core implementation
  • openviking/server/routers/sessions.py:commit_session() - HTTP route
  • sdk/python/openviking_sdk/client.py:AsyncHTTPClient.commit_session() - Python SDK
  • crates/ov_cli/src/commands/session.rs:commit_session() - CLI command

2. Interface and Parameter Description ​

Parameters

ParameterTypeRequiredDefaultDescription
session_idstrYes-Session ID to commit
keep_recent_countintNo0Number of recent live messages to retain (kept live, not archived) after commit. 0 (default) archives all messages.
enable_working_memorybool or nullNonullOverride only WM generation for this commit. Omitted/null inherits the resolved policy; true/false leaves self/peer/memory_types and saved policies unchanged. Strings/numbers are rejected. The response includes effective_enable_working_memory.
reset_contextboolNofalseHTTP API: archive all live messages, then append a boundary archive containing only a .done marker with context_reset. Keeps the session ID and raw history, clears injected context and stops future summaries from inheriting pre-reset overviews. Requires keep_recent_count=0 and no retention_mode.

reset_context is used by the OpenClaw plugin reset hook and Session.commit_async(). It also creates a boundary when there are no live messages, unless the newest archive is already a reset boundary. Memory extraction for older archives can finish independently; long-term memories are preserved. The SDK and CLI do not expose a dedicated reset_context option; use the HTTP API when needed.

The effective policy is resolved in this order: Session .meta.json, latest settings/user_config.json, then the kernel default. The fully resolved policy is stored in the queued task before Phase 2 starts.

3. Usage Examples ​

HTTP API

http
POST /api/v1/sessions/{session_id}/commit
bash
# Commit session (returns immediately)
curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/commit \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key"

# Poll task status
curl -X GET http://localhost:1933/api/v1/tasks/{task_id} \
  -H "X-API-Key: your-key"

Python SDK

python
import openviking_sdk as ov

client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

# Commit finishes Phase 1; summary and memory extraction run in the background
result = client.commit_session(session_id="a1b2c3d4")
print(f"Status: {result['status']}")
print(f"Task ID: {result['task_id']}")

# Check once; poll again if the task is still pending or running
task_id = result.get("task_id")
if task_id:
    task = client.get_task(task_id=task_id)
    print(task["status"])
    if task["status"] == "completed":
        print(task["result"]["memories_extracted"])

TypeScript SDK

typescript
console.log(await client.commitSession("session-id"));

Go SDK

go
commit, err := client.CommitSession(ctx, "a1b2c3d4", &openviking.CommitSessionOptions{
    KeepRecentCount: openviking.Int(0),
})
if err != nil {
    return err
}
fmt.Println(commit["status"], commit["task_id"])

taskID, _ := commit["task_id"].(string)
if taskID != "" {
    task, err := client.GetTask(ctx, taskID)
    if err != nil {
        return err
    }
    fmt.Println(task["status"])
}

CLI

bash
ov session commit a1b2c3d4

Response Example

json
{
  "status": "ok",
  "result": {
    "session_id": "a1b2c3d4",
    "status": "accepted",
    "task_id": "uuid-xxx",
    "archive_uri": "viking://user/alice/sessions/a1b2c3d4/history/archive_001",
    "archived": true
  }
}

No-op Response Example

json
{
  "status": "ok",
  "result": {
    "session_id": "a1b2c3d4",
    "status": "skipped",
    "task_id": null,
    "archive_uri": null,
    "archived": false,
    "reason": "no_messages"
  }
}

Session Properties ​

PropertyTypeDescription
uristrSession Viking URI (viking://user/{user_id}/sessions/{session_id}/)
messagesList[Message]Current messages in the session
statsSessionStatsSession statistics
summarystrCompression summary

Session Storage Structure ​

viking://user/{user_id}/sessions/{session_id}/
+-- .abstract.md              # L0: Session overview
+-- .overview.md              # L1: Key decisions
+-- messages.jsonl            # Current messages
+-- tools/                    # Tool executions
|   +-- {tool_id}/
|       +-- tool.json
+-- .meta.json                # Metadata
+-- history/                  # Archived history
    +-- archive_001/
    |   +-- messages.jsonl    # Written in Phase 1
    |   +-- .abstract.md      # Written in Phase 2 (background)
    |   +-- .overview.md      # Written in Phase 2 (background)
    |   +-- .meta.json        # Archive metadata
    |   +-- memory_diff.json  # Written when long-term memory extraction completes
    |   +-- .done             # Phase 2 completion marker
    |   +-- .failed.json      # Phase 2 failure marker
    +-- archive_002/

memory_diff.json Structure ​

When long-term memory extraction runs successfully, the commit writes a memory_diff.json to the archive directory, recording all memory changes for auditing and reviewing changes:

json
{
  "archive_uri": "viking://user/{user_id}/sessions/{session_id}/history/archive_001",
  "extracted_at": "2026-04-21T10:00:00Z",
  "operations": {
    "adds": [
      {
        "uri": "viking://user/alice/memories/profile.md",
        "memory_type": "profile",
        "after": "Newly created file content"
      }
    ],
    "updates": [
      {
        "uri": "viking://user/alice/memories/preferences/project.md",
        "memory_type": "preferences",
        "before": "Content before modification",
        "after": "Content after modification"
      }
    ],
    "deletes": [
      {
        "uri": "viking://user/alice/memories/preferences/old.md",
        "memory_type": "preferences",
        "deleted_content": "Deleted file content"
      }
    ]
  },
  "skipped_operations": [
    {
      "memory_type": "events",
      "page_id": 101,
      "reason_code": "invalid_ranges",
      "reason": "No valid event range could be resolved"
    }
  ],
  "summary": {
    "total_adds": 1,
    "total_updates": 1,
    "total_deletes": 1,
    "total_skipped": 1
  }
}
FieldTypeDescription
archive_uristrArchive directory URI for this commit
extracted_atstrISO 8601 timestamp of extraction
operations.addsarrayNew memories created (uri, memory_type, after)
operations.updatesarrayModified memories (uri, memory_type, before, after)
operations.deletesarrayDeleted memories (uri, memory_type, deleted_content)
skipped_operationsarrayIntentionally skipped operations and their stable reason codes; these do not represent file changes
summary.total_addsintNumber of new memories
summary.total_updatesintNumber of modified memories
summary.total_deletesintNumber of deleted memories
summary.total_skippedintNumber of intentionally skipped operations

An empty memory_diff.json (all counts zero) is written when long-term memory extraction runs but produces no applied or intentionally skipped operations.

Full Example ​

Python SDK

python
import time

from openviking_sdk import SyncHTTPClient, ContextPart, TextPart

# Initialize client
client = SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

try:
    # Create new session
    session_result = client.create_session()
    session_id = session_result["session_id"]
    print(f"Session created: {session_id}")

    # Add user message
    client.add_message(
        session_id=session_id,
        role="user",
        content="How do I configure embedding?",
    )

    # Search with session context
    results = client.search(
        query="embedding configuration",
        session_id=session_id,
    )

    # Add assistant message with context reference
    resources = results.get("resources", [])
    if resources:
        resource = resources[0]
        client.add_message(
            session_id=session_id,
            role="assistant",
            parts=[
                TextPart(text="Based on the documentation, you can configure embedding..."),
                ContextPart(
                    uri=resource["uri"],
                    context_type="resource",
                    abstract=resource.get("abstract", ""),
                ),
            ],
        )
    # Commit session; summary and memory extraction run in the background
    commit_result = client.commit_session(session_id=session_id)
    print(f"Task ID: {commit_result['task_id']}")

    # Optional: poll for completion
    task_id = commit_result.get("task_id")
    if task_id:
        for _ in range(30):
            task = client.get_task(task_id=task_id)
            if task and task["status"] == "completed":
                print(task.get("result"))
                break
            if task and task["status"] in {"failed", "cancelled"}:
                raise RuntimeError(task)
            time.sleep(1)
        else:
            print(f"Still pending: {task_id}; check this task again later")
finally:
    client.close()

HTTP API

bash
# Step 1: Create session
curl -X POST http://localhost:1933/api/v1/sessions \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key"
# Returns: {"status": "ok", "result": {"session_id": "a1b2c3d4"}}

# Step 2: Add user message
curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{"role": "user", "content": "How do I configure embedding?"}'

# Step 3: Search with session context
curl -X POST http://localhost:1933/api/v1/search/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{"query": "embedding configuration", "session_id": "a1b2c3d4"}'

# Step 4: Add assistant message
curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{"role": "assistant", "content": "Based on the documentation, you can configure embedding..."}'

# Step 5: Commit session (an archived commit returns a task_id)
curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/commit \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key"
# Returns: {"status": "ok", "result": {"status": "accepted", "task_id": "uuid-xxx", ...}}

# Step 6: Check the background task; poll again if it has not finished
curl -X GET http://localhost:1933/api/v1/tasks/uuid-xxx \
  -H "X-API-Key: your-key"

Best Practices ​

Commit Regularly ​

python
# Commit after significant interactions
session_info = client.get_session(session_id=session_id)
if session_info["message_count"] > 10:
    client.commit_session(session_id=session_id)
python
# Interpret the query using session context; results depend on relevance and query-planning settings
results = client.search(query=query, session_id=session_id)

Open source under the AGPL-3.0 License. Font licenses