- 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>
425 lines
12 KiB
Markdown
425 lines
12 KiB
Markdown
# 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:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
```python
|
|
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
|
|
|
|
---
|
|
|
|
### 2. Smart Create Wiki Page (Recommended for Research)
|
|
|
|
**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
|
|
|
|
```python
|
|
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:**
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
```python
|
|
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.
|
|
|
|
```python
|
|
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.
|
|
|
|
```python
|
|
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"
|
|
|
|
```python
|
|
# 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"
|
|
|
|
```python
|
|
# 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"
|
|
|
|
```python
|
|
# 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"
|
|
|
|
```python
|
|
# 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.
|