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>
This commit is contained in:
@@ -0,0 +1,424 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user