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.
Keep multer on the same route or path prefix as the adapter mount, and don’t put a generic body
parser in front of multipart routes.
Body size limits
Like the runtime’s own reference bridge, 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:413 on
limits.fileSize overflow) or add an express.raw({ type: 'multipart/form-data', limit: ... })
guard ahead of the mount. Choose limits that match your product — typical chat attachments are
1–25 MB.
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.