npx skills add ...
npx skills add pipefy/ai-toolkit --skill pipefy-attachments
Use this skill when the user wants to upload a file to a Pipefy card or table-record attachment field. Covers local and downloaded file sources, plus a presigned-URL handshake for uploading files directly.
npx skills add pipefy/ai-toolkit --skill pipefy-attachments
MCP clients: read references/mcp.md. CLI users: read references/cli.md. Examples below describe shared operation arguments.
Upload one file at a time to a card or table-record attachment field. The upload goes through Pipefy's presigned URL flow (request URL, S3 PUT, then field update).
Do not use this skill for:
organization_id. Find it via get_organization or get_pipe.card_id or table_record_id.document_upload,
not the field's uuid). Find it on the card or table record fetch tools.| Operation | Read-only |
|---|---|
upload_attachment_to_card | No |
upload_attachment_to_table_record | No |
create_attachment_presigned_url | No |
file_name is inferred from the source basename when omitted, so callers
usually only pass the four IDs and the source.
Operation arguments:
When the URL has no filename in its path (e.g. .../download?id=1), pass
file_name explicitly so Pipefy stores it under a real name.
Operation arguments:
To store the attachment under a different name than the source basename, pass
file_name explicitly. It wins over the inferred basename.
When the one-shot upload cannot reach the bytes or exceeds its 100 MiB cap, use
create_attachment_presigned_url and upload from an environment that can read the file:
create_attachment_presigned_url with organization_id + file_name
(optional content_type / content_length). It returns upload_url (the S3
PUT url), storage_path (the object key), and expires_in_seconds.PUT the file bytes
to upload_url within expires_in_seconds (send Content-Type /
Content-Length matching what you passed, if any).[storage_path] via update_card_field /
set_table_record_field_value. Store storage_path, never a URL — the signed
download URL is minted on read.Because the bytes are handled by the client (step 2), not passed through the tool call, this keeps the model's context clean.
upload_attachment_to_card / upload_attachment_to_table_record (one-shot):
the upload result has a download_url (the signed URL Pipefy
returns), the inferred or explicit content_type, and the file_size in
bytes, and the attachment field on the card or record now lists the file. One
call is the whole job.
create_attachment_presigned_url (handshake) is not done at mint:
a successful result here only means a target was minted — no field was touched and
nothing is attached yet. Done means you completed all three steps: after the
client PUTs the bytes to upload_url and you set the field to [storage_path],
the attachment field lists the file. Do not treat the mint response (or its
premature signed URL) as a finished upload.
Check source accessibility, the 100 MiB one-shot limit, upload expiry and signed headers, and write access to the attachment field. If a signed URL expires, mint a new one; retrying the PUT against the old URL does not refresh it. The presigned handshake requires checking the client PUT and field update separately from minting.
pipefy-pipes-and-cards: finding card ids and attachment field slugs.pipefy-database-tables: finding table record ids and field slugs.