pipefy-attachments — Claude Code skill: what it does, how to install
Uploads a file into a Pipefy card or table-record attachment field from disk or a URL, with a presigned-URL route for files over 100 MiB.
npx skills add pipefy/ai-toolkit --skill pipefy-attachments -a claude-codeWhat pipefy-attachments does
This skill puts a single file into an attachment field on a Pipefy card or table record. The file comes from a local path (file_path) or a URL (file_url). The name is taken from the source basename; if a URL has no filename in it, like .../download?id=1, pass file_name yourself.
Three operations sit underneath: upload_attachment_to_card, upload_attachment_to_table_record and create_attachment_presigned_url. The first two finish in one call. The third covers files over 100 MiB or bytes the agent cannot reach. It returns upload_url and storage_path, you PUT the file, then write [storage_path] into the field with update_card_field or set_table_record_field_value.
Before you start, gather the organization_id and the target card or record id, and look up the field slug (something like document_upload, not the uuid). A presigned URL expires, and retrying the PUT against the old one won't help, so mint a fresh one. One file per call means bulk uploads need a loop on the agent side.
What it helps with
- attach a report from disk to a Pipefy card
- pull a file from a URL into a table record field
- store an attachment under a different name than the source file
- upload a file over 100 MiB through a presigned URL
- name a download whose URL has no filename
Example prompts for the agent
- Attach ~/report.pdf to card 1234 in the document_upload field
- Download the file at this URL and upload it to table record tr-555 as Invoice-2026.pdf
- This file is too big for a normal upload: get a presigned URL and attach it to card 1234
How to install pipefy-attachments
1Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-attachments -a claude-code2Manually: put the files in place
~/.claude/skills/pipefy-attachments/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/pipefy-attachments/
1Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-attachments -a codex2Manually: put the files in place
.agents/skills/pipefy-attachments/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-attachments -a cursor2Manually: put the files in place
.cursor/skills/pipefy-attachments/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install pipefy/ai-toolkit pipefy-attachments2Manually: put the files in place
.github/skills/pipefy-attachments/SKILL.md1Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-attachments -a gemini-cli2Platform CLI
gemini skills install https://github.com/pipefy/ai-toolkit --path plugins/pipefy/skills/pipefy-attachmentsManually: put the files in place
.devin/skills/pipefy-attachments/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-attachments -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about pipefy-attachments
How do I install pipefy-attachments in Claude Code?
Run npx skills add pipefy/ai-toolkit --skill pipefy-attachments -a claude-code. The skill lands in ~/.claude/skills/pipefy-attachments/SKILL.md.
What does pipefy-attachments do?
It uploads one file into an attachment field on a Pipefy card or table record. The source can be a local path via file_path or a link via file_url.
When should I use create_attachment_presigned_url instead of a normal upload?
When the file is over 100 MiB or the agent can't read it directly. You get upload_url and storage_path, PUT the bytes yourself, then set the field to [storage_path]. Until that last step, nothing is attached.
Source text
SKILL.md · Apache-2.0
--- name: pipefy-attachments description: > 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. tags: [pipefy, attachments, upload, card, table-record] metadata: surfaces: "mcp cli" --- # Attachments MCP clients: read [references/mcp.md](references/mcp.md). CLI users: read [references/cli.md](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). --- ## When to use - The user says "attach this file to card X" or "upload to the documents field on record Y". - Pick the source by where the bytes actually are. Use the source rules for your chosen surface. Do not use this skill for: - Reading or listing existing attachments. There is no list/download tool in this skill scope. Cards and table records expose their attachments through the regular card/record fetch tools. - Bulk uploads. One file per call; iterate at the agent layer. ## Prerequisites - A Pipefy `organization_id`. Find it via `get_organization` or `get_pipe`. - A target `card_id` or `table_record_id`. - The attachment field's slug (the human-readable id like `document_upload`, not the field's uuid). Find it on the card or table record fetch tools. - Exactly one file source accessible to the chosen upload surface. ## Tools needed | Operation | Read-only | | ------------ | ----------- | | `upload_attachment_to_card` | No | | `upload_attachment_to_table_record` | No | | `create_attachment_presigned_url` | No | ## Steps ### Upload a local file to a card `file_name` is inferred from the source basename when omitted, so callers usually only pass the four IDs and the source. Operation arguments: ```text upload_attachment_to_card(organization_id=42, card_id=1234, field_id=document_upload, file_path=~/report.pdf) ``` ### Upload from a URL ```text upload_attachment_to_card(organization_id=42, card_id=1234, field_id=document_upload, file_url=https://example.com/report.pdf) ``` 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. ### Upload a local file to a table record Operation arguments: ```text upload_attachment_to_table_record(organization_id=42, table_record_id=tr-555, field_id=document_upload, file_path=/tmp/export.csv) ``` ## Overriding the file name To store the attachment under a different name than the source basename, pass `file_name` explicitly. It wins over the inferred basename. ```text upload_attachment_to_card(..., file_url=https://example.com/abc123.pdf, file_name=Invoice-2026.pdf) ``` ## Use the presigned handshake 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: 1. Call `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`. 2. From an environment that can reach the upload host, HTTP `PUT` the file bytes to `upload_url` within `expires_in_seconds` (send `Content-Type` / `Content-Length` matching what you passed, if any). 3. Set the attachment field to `[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. ## Success criteria **`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. ## Failure modes 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. ## See also - `pipefy-pipes-and-cards`: finding card ids and attachment field slugs. - `pipefy-database-tables`: finding table record ids and field slugs.
© pipefy · Apache-2.0 · pipefy/ai-toolkit