POST /files— single-file upload,filepart required (plus optionalagentId/threadIdform fields)POST /knowledge/:id/documents— one or morefilesparts (plus optionalagentId/threadId)
/files) or capability-gated (/knowledge — enable capabilities.knowledge) routes of the runtime; the adapter’s job is only to translate the incoming multipart body into the runtime’s file/files/body fields.
Native parsing
When a multipart request arrives, the adapter reads the raw stream and parses it with Node’s built-inFormData (undici, shipped with Node 18+) — no multer, busboy, or formidable required:
file part becomes RuntimeRequest.file ({filename, content, contentType}); any other form fields (agentId, threadId) land on RuntimeRequest.body and flow through to the SDK upload call.
Using multer yourself
The adapter coexists withmulter. If your own middleware already parsed the multipart body, the adapter detects the parsed req.file/req.files and honors them instead of reading the stream again:
express.json() on a multipart request, or a multer instance configured to discard), the adapter detects that the stream was already consumed and responds 400 INVALID_REQUEST — it can’t reconstruct the body.
In NestJS, the standard approach is to use FileInterceptor from @nestjs/platform-express on specific routes, or to let the adapter handle multipart natively for the /api/persona/* routes.
Body size limits
The adapter buffers request bodies (JSON and multipart) in memory with no size limit of its own. Enforce one with your own middleware when you need it:limits option:
Downloads are binary
The mirror image:GET /files/:id streams the file back through as raw bytes (kind: 'binary'), chunk by chunk, with the correct Content-Type. The adapter handles Content-Disposition-style headers from the runtime verbatim.