Shelvia
RecipeAvailable

Recipe, Google ADK + Shelvia

Shelvia is the memory layer the ADK calls. The ADK runs the agent; Shelvia returns reviewed context and accepts new memory only through the review queue.

Principle

ADK's function-tool abstraction maps directly onto Shelvia's REST surface. Register one tool for reads (memory.context) and one tool for writes (memory.candidates). The write tool returns a pending candidate id, not a trusted memory id.

Setup

  • Create a Workspace API token in Settings > API with scopes: memory.read + memory.context (read-only agent) OR + memory.candidates (agent that proposes memory).
  • Store the token in SHELVIA_API_KEY. Never log it.
  • Install google-adk per the ADK quickstart in your Python environment.

Pattern, function tool for reads

Register a Shelvia retrieval as an ADK function tool. The agent calls it before generating; the response is a structured context pack.

import os, httpx
from google.adk.agents import Agent
from google.adk.tools import FunctionTool

SHELVIA_BASE = "https://shelvia.net"
SHELVIA_KEY = os.environ["SHELVIA_API_KEY"]

def fetch_shelvia_context(project_id: str, purpose: str) -> dict:
    """Retrieve reviewed Shelvia project memory before acting.

    Returns decisions, sources, prompts, next steps, and constraints
    with a health verdict. Pending candidates are excluded.
    """
    resp = httpx.post(
        f"{SHELVIA_BASE}/api/v1/project-memory/projects/{project_id}/context-pack",
        headers={"Authorization": f"Bearer {SHELVIA_KEY}"},
        json={"purpose": purpose, "max_chars": 12000, "semantic_ranking": True},
        timeout=30.0,
    )
    resp.raise_for_status()
    return resp.json()

shelvia_context_tool = FunctionTool(fetch_shelvia_context)

agent = Agent(
    name="release_coordinator",
    instruction=(
        "Before answering, call fetch_shelvia_context to retrieve reviewed "
        "Shelvia memory. Cite decisions and sources by id."
    ),
    tools=[shelvia_context_tool],
)

Pattern, function tool for candidate write

def propose_shelvia_candidate(
    project_id: str,
    type: str,        # decision | next_step | open_question | prompt | source | note
    title: str,
    content: str,
    source_url: str | None = None,
    run_id: str = "unknown",
) -> dict:
    """Propose a Shelvia memory candidate. Lands in the review queue
    with status pending. A workspace member approves before it becomes
    trusted memory."""
    resp = httpx.post(
        f"{SHELVIA_BASE}/api/v1/project-memory/projects/{project_id}/candidates",
        headers={
            "Authorization": f"Bearer {SHELVIA_KEY}",
            "Idempotency-Key": f"agent-google-adk-{run_id}-{type}-{hash(content)}",
        },
        json={"type": type, "title": title, "content": content, "source_url": source_url},
        timeout=30.0,
    )
    resp.raise_for_status()
    return resp.json()

shelvia_write_tool = FunctionTool(propose_shelvia_candidate)

Propose memory candidates safely

ADK function tools that propose Shelvia memory candidates must follow the candidate-write safety pattern. Agents propose. Humans approve. The candidate enters the review queue; it does not become trusted memory until a workspace member approves.

  • Identity: create a narrow-scope Workspace API token per ADK deployment (label it, e.g., "Google ADK production support agent"). Reuse shv_live_<hex> with memory.candidates + memory.context.
  • Idempotency: every candidate write should carry an Idempotency-Key shaped agent-google-adk-<run-id>-<candidate-hash>. ADK agents may retry on transient failures; idempotency keeps the review queue clean.
  • Runtime tag: call log_shelvia_continuation(suggested_tool="google-adk", ...) at the end of each run. The candidate body itself does not carry a runtime field.
  • Never write to trusted memory directly. There is no propose-and-approve tool. Approval lives only in the Shelvia UI.
  • Never log raw chain-of-thought. ADK exposes the agent's reasoning trace separately; do not put it in candidate content. Keep candidate content to the final claim.
  • Never include secrets or tokens. ADK function-tool docstrings are part of the prompt, keep them clean of credentials. The validator rejects forbidden keys with a structured error code.
  • Agents must not approve their own memory. No ADK function tool can promote a Shelvia candidate. Promotion is human-only.

Observability (optional)

A function tool can log a continuation after the agent run. The event records which reviewed context was used and what should happen next. This is an optional audit / observability emit, it does NOT become trusted memory and does NOT bypass review-before-save. Scope required: continuations.log.

def log_shelvia_continuation(
    project_id: str,
    next_best_action: str,
    why: str | None = None,
    suggested_tool: str = "google-adk",
    priority: str = "normal",
) -> dict:
    """Audit-log a continuation event after an ADK run. Records
    which reviewed context was used and what should happen next.
    Does NOT write to trusted memory."""
    resp = httpx.post(
        f"{SHELVIA_BASE}/api/v1/project-memory/projects/{project_id}/continuations",
        headers={"Authorization": f"Bearer {SHELVIA_KEY}"},
        json={
            "next_best_action": next_best_action,
            "why": why,
            "suggested_tool": suggested_tool,
            "priority": priority,
        },
        timeout=30.0,
    )
    resp.raise_for_status()
    return resp.json()

shelvia_observability_tool = FunctionTool(log_shelvia_continuation)

Safety notes

  • ADK runs the agent. Shelvia is the reviewed memory it retrieves and proposes back into.
  • Every proposed candidate is pending. A workspace member must approve before it becomes trusted memory.
  • The continuation log is audit-only. It does not write to trusted memory tables.
  • Workspace anchor is on the token; the agent cannot retarget Shelvia to a different workspace.
  • The function-tool docstrings are part of the prompt, keep them accurate. Don't claim Shelvia writes trusted memory directly.

Where to go next

  • REST API reference, /docs/developers/api
  • Authentication scopes, /docs/developers/auth
  • Review-before-save concept, /docs/concepts/review-before-save

For runnable code samples and the developer reference, see /developers. For the trust model in depth, see /security.