upload_document
Upload a PDF for compliance verification with automatic PII redaction before storage. Returns a document ID for subsequent retrieval.
Instructions
Upload a PDF to ActaLumen for compliance verification. The server applies organization-configured PII redaction before storage — the agent will only ever see redacted content in subsequent calls. Returns a document ID; the document is PROCESSING until embeddings finish (poll get_document for status=READY).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Absolute or ~/-relative path to a PDF. Must be inside ACTALUMEN_UPLOAD_DIR (default ~/actalumen-inbox) — the user controls which files agents can upload. | |
| id | No | Optional custom document ID (letters, digits, -, _, max 128). Useful for idempotent re-runs. |
Implementation Reference
- src/tools/upload_document.ts:24-54 (handler)Defines the upload_document tool with its handler. The handler resolves the path, validates it's inside the allowed upload directory, checks it's a PDF file, reads it, and sends it as a multipart POST to /v1/documents.
export const uploadDocument = defineTool({ name: "upload_document", description: "Upload a PDF to ActaLumen for compliance verification. The server applies organization-configured PII redaction before storage — the agent will only ever see redacted content in subsequent calls. Returns a document ID; the document is PROCESSING until embeddings finish (poll get_document for status=READY).", inputSchema: Input, handler: async (input, { client, config }) => { const resolved = path.resolve(expandHome(input.path)); const allowed = config.uploadDir; const rel = path.relative(allowed, resolved); if (rel.startsWith("..") || path.isAbsolute(rel)) { throw new Error( `Upload denied: ${resolved} is outside the allowed upload directory (${allowed}). ` + `Move the file there, or set ACTALUMEN_UPLOAD_DIR to a directory containing it.`, ); } const stat = await fs.stat(resolved); if (!stat.isFile()) throw new Error(`Not a file: ${resolved}`); if (!resolved.toLowerCase().endsWith(".pdf")) { throw new Error("Only PDF files are supported."); } const bytes = await fs.readFile(resolved); const form = new FormData(); form.append("file", new Blob([bytes], { type: "application/pdf" }), path.basename(resolved)); if (input.id) form.append("id", input.id); return client.postMultipart("/v1/documents", form); }, }); - src/tools/upload_document.ts:6-17 (schema)Zod schema defining the input for upload_document: 'path' (string, must be inside ACTALUMEN_UPLOAD_DIR) and optional 'id' (string, alphanumeric with - and _, max 128 chars, for idempotent re-runs).
const Input = z.object({ path: z .string() .describe( "Absolute or ~/-relative path to a PDF. Must be inside ACTALUMEN_UPLOAD_DIR (default ~/actalumen-inbox) — the user controls which files agents can upload.", ), id: z .string() .regex(/^[a-zA-Z0-9_-]{1,128}$/) .optional() .describe("Optional custom document ID (letters, digits, -, _, max 128). Useful for idempotent re-runs."), }); - src/tools/index.ts:11-20 (registration)The uploadDocument tool is registered in the tools array exported from src/tools/index.ts, making it available as part of the tool set.
export const tools: ToolDef[] = [ uploadDocument, getDocument, listDocuments, listTemplates, startVerification, getVerification, chatWithDocument, getUsage, ]; - src/tools/upload_document.ts:19-22 (helper)Helper function expandHome that expands tilde (~) to the user's HOME directory, used for path resolution.
function expandHome(p: string): string { if (p.startsWith("~/")) return path.join(process.env.HOME ?? "", p.slice(2)); return p; }