pipefy-api-fallback — скилл для Claude Code: установка
Скилл обращается к Pipefy GraphQL API напрямую, когда операции toolkit и интроспекция не помогли. Нужен для разбора сбоев и запасных запросов.
npx skills add pipefy/ai-toolkit --skill pipefy-api-fallback -a claude-codeЧто делает pipefy-api-fallback
pipefy-api-fallback включает прямой вызов Pipefy GraphQL API через curl или httpx. Он помогает выполнять запросы, мутации и интроспекцию схемы, когда соединение toolkit недоступно или GraphQL завершился инфраструктурной ошибкой. Перед этим скилл должен пройти два уровня: выделенную операцию, затем интроспекцию и execute_graphql.
Для авторизации используются Service Account через OAuth2 или Personal Access Token из переменной окружения. При наличии обоих вариантов выбирается Service Account. Скилл проверяет коды ошибок GraphQL, включая PERMISSION_DENIED, invalid_input и undefinedField, а после неоднозначной записи перечитывает объект до повторной попытки. Прямой HTTP-вызов здесь — третий уровень, поэтому переходить к нему после одной ошибки нельзя.
Какие задачи решает
- выполнить GraphQL-запрос к Pipefy напрямую
- проверить схему через GraphQL-интроспекцию
- разобрать ошибку авторизации или прав доступа
- повторно проверить объект после неоднозначной мутации
Примеры запросов агенту
- Используй
pipefy-api-fallback, если операция toolkit и интроспекция не помогли. - Проверь схему Pipefy через прямой GraphQL-запрос и объясни ошибку.
- После неоднозначной записи перечитай объект и только потом решай, нужен ли повтор.
Как установить pipefy-api-fallback
1Через Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-api-fallback -a claude-code2Вручную: положить файлы
~/.claude/skills/pipefy-api-fallback/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/pipefy-api-fallback/
1Через Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-api-fallback -a codex2Вручную: положить файлы
.agents/skills/pipefy-api-fallback/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-api-fallback -a cursor2Вручную: положить файлы
.cursor/skills/pipefy-api-fallback/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install pipefy/ai-toolkit pipefy-api-fallback2Вручную: положить файлы
.github/skills/pipefy-api-fallback/SKILL.md1Через Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-api-fallback -a gemini-cli2Командой платформы
gemini skills install https://github.com/pipefy/ai-toolkit --path plugins/pipefy/skills/pipefy-api-fallbackВручную: положить файлы
.devin/skills/pipefy-api-fallback/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add pipefy/ai-toolkit --skill pipefy-api-fallback -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Вопросы о pipefy-api-fallback
Как установить pipefy-api-fallback в Claude Code?
Выполни npx skills add pipefy/ai-toolkit --skill pipefy-api-fallback -a claude-code, затем проверь файл ~/.claude/skills/pipefy-api-fallback/SKILL.md.
Что делает pipefy-api-fallback?
Скилл обращается к Pipefy GraphQL API напрямую через curl или httpx, когда два предыдущих уровня разрешения проблемы не сработали. Он также помогает проверить схему и разобрать ошибки API.
Какая авторизация нужна для работы с Pipefy?
Подойдёт Service Account через OAuth2 или Personal Access Token из переменной окружения. Приоритет отдан Service Account, а перед чтением переменной нужно сообщить пользователю, куда уйдёт её значение.
Исходный текст
SKILL.md · Apache-2.0
---
name: pipefy-api-fallback
description: >
Use this skill when a toolkit operation fails AND the introspection skill could
not resolve the problem. This is the last-resort fallback (Tier 3):
call the Pipefy GraphQL API directly using curl or httpx, authenticating
with the Service Account (OAuth2) or a Personal Access Token (PAT)
available as env var. Follow the 3-tier resolution strategy before
reaching this point.
tags: [pipefy, graphql, api, fallback, troubleshooting, curl]
---
# Pipefy API Fallback (Tier 3 — Last Resort)
Read the [MCP reference](references/mcp.md) or [CLI reference](references/cli.md) for the surface you are using. Load only the relevant reference.
This skill activates only after Tiers 1 and 2 have failed. Call the Pipefy GraphQL API directly, bypassing the toolkit connection.
If a write reports failure, re-read the target before changing tiers or retrying. The mutation may already have applied; follow [Ambiguous write failure](#ambiguous-write-failure-re-read-before-retry).
---
## 3-tier resolution strategy (always follow in order)
1. Try a dedicated operation (`create_card`, `get_phase_cards`, `get_phase_allowed_move_targets`, `update_pipe`, etc.). For card/phase seeding and inventory, see `pipefy-pipes-and-cards` — Seed pipe across phases.
2. Use schema introspection and `execute_graphql` when a dedicated operation is unavailable or fails unexpectedly. See `pipefy-introspection`.
3. Use direct HTTP only when the toolkit connection is unavailable or GraphQL execution fails with an infrastructure error.
**Do not jump to Tier 3 after a single failure.** Follow the tiers in order. Testing a new mutation belongs in Tier 2.
---
## Authentication
Two options (use whichever is available in the environment). Prefer the Service Account when both exist.
To see which variables are set, list their names only, never their values:
```bash
env | cut -d= -f1 | grep '^PIPEFY_'
```
Do not run `env`, `printenv`, or `echo` on these variables to choose an option: that prints the secret into the conversation before the user agrees.
Before reading any `PIPEFY_*` variable, tell the user which variable you will read and that its value goes to `app.pipefy.com` in the `Authorization` header or the token request, and wait for a yes. Do not read it from a file the user did not name.
**Option A — OAuth2 Client Credentials (preferred):**
```bash
TOKEN=$(curl -s -X POST https://app.pipefy.com/oauth/token \
-H "Content-Type: application/json" \
-d "{\"grant_type\":\"client_credentials\",\"client_id\":\"$PIPEFY_SERVICE_ACCOUNT_CLIENT_ID\",\"client_secret\":\"$PIPEFY_SERVICE_ACCOUNT_CLIENT_SECRET\"}" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
```
**Option B — Personal Access Token (PAT):**
```bash
TOKEN="$PIPEFY_PAT" # or $PIPEFY_TOKEN
```
PATs are deprecated for new integrations but may still exist in the environment.
### Token rules
- The `Bearer ` prefix is **mandatory** — Pipefy rejects requests without it.
- Never expose `PIPEFY_SERVICE_ACCOUNT_CLIENT_ID`, `PIPEFY_SERVICE_ACCOUNT_CLIENT_SECRET`, `PIPEFY_PAT`, or `PIPEFY_TOKEN` in responses to the user or in logs.
- Service Account tokens are reused while valid; only re-fetch on expiry (401).
---
## Endpoints
| Purpose | URL |
|---------|-----|
| Queries, mutations, and introspection | `https://app.pipefy.com/graphql` |
| OAuth2 token | `https://app.pipefy.com/oauth/token` |
This one endpoint serves queries, mutations, and introspection of the public schema, and `https://api.pipefy.com/graphql` answers the same way. It is the endpoint the toolkit uses for the public schema (`PIPEFY_BASE_URL` plus `/graphql`). Portal tools and a few others use two more endpoints, `/graphql/interfaces` and `/internal_api`; see [`docs/mcp/tools/portal.md`](https://github.com/pipefy/ai-toolkit/blob/main/docs/mcp/tools/portal.md).
---
## Execute a GraphQL query
```bash
curl -s -X POST https://app.pipefy.com/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "{ me { id name } }"}' | jq .
```
## Execute a GraphQL mutation
```bash
curl -s -X POST https://app.pipefy.com/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation CreateCard($input: CreateCardInput!) { createCard(input: $input) { card { id } } }",
"variables": {
"input": {
"pipe_id": 67890,
"title": "Fallback Card"
}
}
}' | jq .
```
---
## Introspection via raw API
When you need to discover schema over direct HTTP, call the same endpoint:
```bash
# All queries and mutations
curl -s -X POST https://app.pipefy.com/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ __schema { queryType { fields { name description } } mutationType { fields { name description } } } }"}'
# Type details
curl -s -X POST https://app.pipefy.com/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ __type(name: \"CreateCardInput\") { inputFields { name description type { name kind ofType { name kind } } } } }"}'
```
---
## Error code → cause
GraphQL errors, including syntax errors (`GRAPHQL_PARSE_FAILED`), return HTTP 200: check the `errors` array and its `extensions.code`, not the HTTP status code. An authentication failure returns HTTP 401, and a request body that is not valid JSON returns HTTP 500 with a plain-text page.
| Code | Likely cause | Recovery |
|-------|--------------|----------|
| HTTP 401, body `{"errors": [{"title": "Unauthorized", ...}]}` | `Authorization` header missing or empty, or the token sent without the `Bearer ` prefix | Fix the header: `Authorization: Bearer $TOKEN`, with a non-empty token. |
| HTTP 401, body `{"error": "invalid_token", ...}` | Bearer token present but invalid or expired | Re-fetch the token (Option A). |
| PERMISSION_DENIED | Service Account not a member of this pipe/table; Pipefy also answers this for a pipe or card ID that does not exist | Verify the ID; add the SA via `invite_members` or ask the user. |
| resource_not_found | ID does not exist or SA cannot see it | Verify ID; check pipe/table membership. |
| invalid_input | Wrong argument name or type | Run `introspect_type` (Tier 2) to recheck the input shape. |
| undefinedField | The query selects a field the type does not have | Run `introspect_type` on the type and fix the selection. |
| INTERNAL_SERVER_ERROR | API bug or unsupported payload | **Do NOT retry the same payload.** Try an alternative mutation or workaround. |
| missingRequiredInputObjectAttribute | A required field is missing from the input | Compare the payload against `__type(name: …InputType)`. |
| Ambiguous write failure (`success: false`, empty or unclear message) | Mutation may already have applied (side effects on the server) | **Re-read before any retry** — see [Ambiguous write failure](#ambiguous-write-failure-re-read-before-retry). |
---
## Ambiguous write failure (re-read before retry)
Write operations and `execute_graphql` can report failure even when the mutation already applied. Blind retry duplicates customer data (e.g. many cards created despite `success: false`).
1. **Do not** immediately re-run the same create/mutation.
2. **Re-read** first: `get_cards` / `get_phase_cards_count` / returned ids / `cards_count` on the pipe or phase you targeted. Prefer comparing to a count or id set you recorded **before** the write when available.
3. Retry **only** if the re-read clearly shows the write did not land.
4. If the re-read is **inconclusive** (no pre-write baseline, pagination truncates results, or counts cannot prove absence), **stop** — report the ambiguous failure and the re-read evidence to the user. Do not guess-retry.
5. **Hard stop — no client-side idempotency:** `CreateCardInput` has no `idempotency_key` (only `clientMutationId`, which is not create-idempotency). Do not invent client-side keys or assume retries are safe. Re-read is the only safe path until the API adds real idempotency.
---
## Known workarounds
### Cross-pipe card creation
- `createAutomation` with `action: create_card` + `field_map` can return `INTERNAL_SERVER_ERROR` for a cross-pipe target. Do not retry that payload unchanged.
- For a **one-time** connected card, `createCard` with `throughConnectors` can create the card when a connector field has `canCreateNewConnected: true`.
- `createCard` does not create an automation rule. If the user needs future cards created automatically, report that the one-time call does not meet that requirement.
### Pipe listing shorter than `pipesCount`
- `pipesCount` is the org-wide total; `organization { pipes { ... } }` and `search_pipes` return only the pipes the calling identity is a member of. A shorter listing, or an empty one, is expected behavior and not an error. Role does not widen it: a `super_admin` gets the same membership-scoped result. Detail and workarounds: [`docs/mcp/tools/organization.md`](https://github.com/pipefy/ai-toolkit/blob/main/docs/mcp/tools/organization.md#why-counts-disagree).
- `organization { pipes(include_publics: true) }` widens the listing with pipes that are public inside the org. It still normally returns fewer than `pipesCount`.
- Service accounts hit this most often: an SA starts as a member of nothing.
- Pipes created via API are automatically visible to the SA.
- Pipes created in the UI require the SA to be added as an admin.
- Workaround: get pipe IDs from the user once and query `pipe(id: "...")` directly.
### `invite_members` accepts unknown emails silently
- Pipefy mints a new `user_id` for typo addresses without rejecting the invite. Sanity-check email syntax before calling.
---
## External resources (when raw API also fails)
- Pipefy developer portal:
- https://developers.pipefy.com/reference/cards
- https://developers.pipefy.com/reference/pipes
- https://developers.pipefy.com/reference/automation-creation
- https://developers.pipefy.com/reference/how-to-handle-errors
- API reference:
- https://api-docs.pipefy.com/reference/mutations/overview/
- https://api-docs.pipefy.com/reference/queries/overview/
- Community + changelog:
- https://community.pipefy.com/api-76
- https://developers.pipefy.com/changelog
- Status page: https://status.pipefy.com
Search for the exact error message + "Pipefy GraphQL", or the mutation name + "example Pipefy API".
---
## Escalation to the user (absolute last resort)
Only after all 3 tiers and external resources have failed:
1. State exactly what was tried (dedicated operation, introspection, raw API).
2. Show the verbatim error response.
3. Propose a concrete workaround (e.g., "create via the Pipefy UI, then continue via API with the resulting ID").
4. Stop — do not loop.
---
## Success criteria
- The operation completes without an HTTP 4xx/5xx error.
- The response contains a `data` key and `errors` is null or absent.
## Failure modes
- **HTTP 401**: header missing, empty, or without `Bearer ` (body `Unauthorized`), or the token is invalid or expired (body `invalid_token`). Fix the header, or re-fetch the OAuth token (Option A).
- **`GRAPHQL_PARSE_FAILED` at HTTP 200**: GraphQL syntax error. Validate the query string and escape quotes properly when embedding via shell.
- **HTTP 500**: first check that the request body is valid JSON, because a malformed body also returns 500. If it is, treat it as a Pipefy API outage: check [status.pipefy.com](https://status.pipefy.com) and retry later. Do not loop.
- **`INTERNAL_SERVER_ERROR` in `errors` array** — do NOT retry the same payload; pick a different mutation path.
- **Ambiguous write failure** — reported error with empty/unclear message after a create or other write: re-read counts/ids before retrying; never blind-retry creates ([Ambiguous write failure](#ambiguous-write-failure-re-read-before-retry)).
## Security notes
- Never log or print tokens in plain text.
- Prefer environment variables over inline credentials.
- Use `PIPEFY_TOKEN` / `PIPEFY_PAT` only for personal/development use; use service-account credentials (`PIPEFY_SERVICE_ACCOUNT_CLIENT_ID` + `PIPEFY_SERVICE_ACCOUNT_CLIENT_SECRET`) for service accounts.
## See also
- `pipefy-introspection` — Tier 2: use `execute_graphql` and introspection tools before falling back to direct HTTP.
© pipefy · Apache-2.0 · pipefy/ai-toolkit