Files
tatlock/docs/library-desk-requirements.md
T
jpmschweitzerandClaude Opus 4.5 ebac19ba6e docs: add library-desk integration requirements
- Document required endpoints for wiki write operations
- Include implementation guide for smart-create endpoint
- Decision flow for when to use each write tool

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 21:31:05 +01:00

12 KiB

Library-Desk API Requirements for Tatlock Integration

Overview

The Librarian agent in Tatlock needs additional endpoints in library-desk to support wiki page editing and content management. Currently, the API provides read operations but The Librarian needs write capabilities for:

  • Creating new wiki pages
  • Updating existing wiki pages (content, title, tags, description)

Required Endpoints

1. Create Wiki Page (Already Exists)

Endpoint: POST /wiki/pages

This endpoint already exists and works correctly.

2. Update Wiki Page (Needs Enhancement)

Endpoint: PUT /wiki/pages/{page_id}

Current Status: May exist but needs verification that it supports partial updates.

Required Behavior:

  • Accept partial updates (only provided fields should be updated)
  • Support updating: content, title, tags, description
  • Auto-update vector embeddings after content changes
  • Auto-update knowledge graph after content changes

Request Body:

{
    "content": "# New Content\n\nOptional - only if changing content",
    "title": "Optional - only if renaming",
    "tags": ["optional", "list", "of", "new", "tags"],
    "description": "Optional new description"
}

Query Parameters:

  • user: User identifier for multi-tenancy (required)

Response:

{
    "id": 42,
    "path": "/projects/example",
    "title": "Updated Title",
    "description": "Updated description",
    "content": "# New Content...",
    "tags": ["updated", "tags"],
    "updated_at": "2024-01-15T10:30:00Z"
}

Notes:

  • Should trigger background tasks to re-index vectors and refresh graph entities
  • Should validate that user has access to the page (namespace check)
  • Should preserve fields that are not provided in the request

Use Cases for The Librarian

Adding New Knowledge

When a user says "Add this to the wiki" or "Create a page about X":

  • Librarian uses POST /wiki/pages to create the page
  • Tags are assigned based on context (dossiers)

Correcting Information

When a user says "Update the page about X" or "Fix this fact":

  1. Librarian searches for the page with GET /wiki/search
  2. Fetches full content with GET /wiki/pages/{id}
  3. Updates with corrected content via PUT /wiki/pages/{id}

Organizing Knowledge

When a user says "Add this page to the projects dossier":

  • Librarian updates just the tags field via PUT /wiki/pages/{id}

Integration Notes

  • The Librarian will call these endpoints via HTTP from Tatlock
  • Authentication uses Bearer token (LIBRARY_DESK_API_KEY)
  • All operations are scoped to the user's namespace
  • Background processing (vectors, graph) should not block the response

Testing Checklist

  • PUT /wiki/pages/{page_id} accepts partial updates
  • Updating content triggers vector re-indexing
  • Updating content triggers graph entity extraction
  • Tags can be updated independently of content
  • Description can be updated independently
  • Title can be updated (with path remaining the same)
  • User namespace validation works correctly

===== IMPLEMENTATION INSTRUCTIONS =========

Librarian Wiki Integration Guide

This document provides implementation instructions for integrating the library-desk wiki endpoints into the Librarian agent (Tatlock).

Available Endpoints

1. Create Wiki Page

Endpoint: POST /wiki/pages

Use this for simple page creation when the Librarian already has the content.

async def create_wiki_page(
    title: str,
    path: str,
    content: str,
    tags: list[str],
    description: str = "",
    user: str = "default"
) -> dict:
    """Create a new wiki page."""
    response = await http_client.post(
        f"{LIBRARY_DESK_URL}/wiki/pages",
        headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"},
        json={
            "title": title,
            "path": path,
            "content": content,
            "tags": tags,
            "description": description,
            "user": user
        }
    )
    return response.json()

When to use:

  • User provides specific content to add
  • Librarian has already composed the content
  • Simple note-taking or quick additions

Endpoint: POST /wiki/pages/smart-create

Use this when the Librarian should research a topic before creating the page. This endpoint:

  1. Searches existing wiki, knowledge graph, and web for context
  2. Uses LLM to synthesize findings into structured content
  3. Creates the page with proper attribution
  4. Automatically links entities bidirectionally
async def smart_create_wiki_page(
    topic: str,
    tags: list[str],
    user: str = "default",
    path: str | None = None,
    include_web_research: bool = True,
    include_wiki_search: bool = True
) -> dict:
    """Create a wiki page with HybridRAG research."""
    response = await http_client.post(
        f"{LIBRARY_DESK_URL}/wiki/pages/smart-create",
        headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"},
        json={
            "topic": topic,
            "path": path,  # Optional - auto-generated from topic if not provided
            "tags": tags,
            "user": user,
            "include_web_research": include_web_research,
            "include_wiki_search": include_wiki_search
        }
    )
    return response.json()

Response includes:

{
  "page": {
    "id": 123,
    "path": "/users/jpmschweitzer/technology/docker-orchestration",
    "title": "Docker orchestration",
    "content": "# Docker Orchestration\n\n...",
    "tags": ["technology", "devops"],
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z"
  },
  "research_summary": {
    "wiki_results": 3,
    "web_results": 8,
    "graph_entities": 5,
    "keywords_extracted": 12,
    "timing_ms": 4500
  },
  "sources_used": 11,
  "search_id": "uuid-for-reference",
  "entity_linking": {
    "forward_links": 5,
    "backward_links": 3,
    "pages_updated": 2
  }
}

When to use:

  • User says "Create a page about X"
  • User says "Add information about X to the wiki"
  • Librarian needs to research before writing
  • Topic benefits from context from existing knowledge

3. Update Wiki Page

Endpoint: PUT /wiki/pages/{page_id}

Use this for modifying existing pages. Supports partial updates.

async def update_wiki_page(
    page_id: int,
    user: str = "default",
    content: str | None = None,
    title: str | None = None,
    tags: list[str] | None = None,
    description: str | None = None
) -> dict:
    """Update an existing wiki page (partial updates supported)."""
    # Only include fields that are being updated
    update_data = {}
    if content is not None:
        update_data["content"] = content
    if title is not None:
        update_data["title"] = title
    if tags is not None:
        update_data["tags"] = tags
    if description is not None:
        update_data["description"] = description

    response = await http_client.put(
        f"{LIBRARY_DESK_URL}/wiki/pages/{page_id}?user={user}",
        headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"},
        json=update_data
    )
    return response.json()

When to use:

  • User says "Update the page about X"
  • User says "Fix this information"
  • User says "Add this page to the projects dossier" (update tags only)
  • Correcting or enhancing existing content

4. Search Wiki Pages

Endpoint: GET /wiki/search

Use this to find existing pages before updating.

async def search_wiki(
    query: str,
    user: str = "default"
) -> dict:
    """Search wiki pages."""
    response = await http_client.get(
        f"{LIBRARY_DESK_URL}/wiki/search",
        headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"},
        params={"q": query, "user": user}
    )
    return response.json()

5. Get Wiki Page

Endpoint: GET /wiki/pages/{page_id}

Use this to fetch full page content before editing.

async def get_wiki_page(
    page_id: int,
    user: str = "default"
) -> dict:
    """Get a wiki page by ID."""
    response = await http_client.get(
        f"{LIBRARY_DESK_URL}/wiki/pages/{page_id}",
        headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"},
        params={"user": user}
    )
    return response.json()

Decision Flow for Librarian

User Request
    │
    ▼
┌─────────────────────────────────────────────┐
│ Does user want to CREATE or UPDATE a page?  │
└─────────────────────────────────────────────┘
    │                           │
    ▼                           ▼
  CREATE                      UPDATE
    │                           │
    ▼                           ▼
┌─────────────────┐    ┌──────────────────────┐
│ Does Librarian  │    │ Search for the page  │
│ need to research│    │ GET /wiki/search     │
│ the topic?      │    └──────────────────────┘
└─────────────────┘              │
    │         │                  ▼
    ▼         ▼         ┌──────────────────────┐
   YES        NO        │ Get full page content│
    │         │         │ GET /wiki/pages/{id} │
    ▼         ▼         └──────────────────────┘
┌─────────┐ ┌─────────┐          │
│ smart-  │ │ POST    │          ▼
│ create  │ │ /wiki/  │  ┌──────────────────────┐
│         │ │ pages   │  │ Update the page      │
└─────────┘ └─────────┘  │ PUT /wiki/pages/{id} │
                         └──────────────────────┘

Common Use Cases

1. "Create a page about Docker Compose"

# Use smart-create for research-backed content
result = await smart_create_wiki_page(
    topic="Docker Compose",
    tags=["technology", "devops", "containers"],
    user="jpmschweitzer"
)
# Returns page with synthesized content from wiki + web research

2. "Add this note to the wiki: Remember to renew SSL cert on Jan 15"

# Use simple create for user-provided content
result = await create_wiki_page(
    title="SSL Certificate Renewal Reminder",
    path="/reminders/ssl-renewal",
    content="# SSL Certificate Renewal\n\nRemember to renew SSL cert on Jan 15",
    tags=["reminders", "infrastructure"],
    user="jpmschweitzer"
)

3. "Update the page about my home server to add the new IP"

# 1. Search for the page
search_results = await search_wiki("home server", user="jpmschweitzer")
page_id = search_results["results"][0]["id"]

# 2. Get current content
page = await get_wiki_page(page_id, user="jpmschweitzer")

# 3. Modify content (Librarian edits the markdown)
new_content = page["content"] + "\n\n## Updated IP\n\nNew IP: 192.168.1.100"

# 4. Update the page
result = await update_wiki_page(
    page_id=page_id,
    content=new_content,
    user="jpmschweitzer"
)

4. "Add this page to the projects dossier"

# Update only tags (partial update)
result = await update_wiki_page(
    page_id=page_id,
    tags=["projects", "existing-tag"],  # Add "projects" tag
    user="jpmschweitzer"
)

Background Processing

All write operations trigger background tasks that:

  1. Vector Indexing: Chunks content and generates embeddings in Qdrant
  2. Graph Extraction: Extracts entities and creates Neo4j relationships
  3. Entity Linking: (smart-create only) Links entities bidirectionally

These run asynchronously and don't block the API response.


Authentication

All endpoints require Bearer token authentication:

Authorization: Bearer {LIBRARY_DESK_API_KEY}

Multi-Tenancy

All operations are scoped to the user's namespace:

  • Pages are stored under /users/{user}/...
  • Vector collections are per-user: library_desk_{user}
  • Graph nodes are labeled per-user: User_{User}_Document

Always pass the user parameter to ensure proper isolation.