| name | pawrly-add-source |
| description | Author or repair a Pawrly source in pawrly.yaml so its data becomes queryable SQL tables — local/object-store files, REST/GraphQL & OpenAPI HTTP APIs, Postgres/MySQL/SQLite/DuckDB, Snowflake, Iceberg/Delta/DuckLake, or another MCP server. Use when adding, connecting, editing, or troubleshooting a source, wiring credentials via secrets, or setting caching and safety guards. After it resolves, query through the `pawrly` skill. |
| version | 0.1.0 |
Pawrly: add a source
Use this skill to author or fix a Pawrly source — a named connection exposed as SQL tables addressed <source>.<table> (the source name is the schema prefix). Sources live under sources: in pawrly.yaml.
Goal
A valid, queryable source that passes:
pawrly validate
pawrly check --source <name>
pawrly schema <name>.<table>
Workflow
- Read the upstream first — the API docs, the file layout, or the database catalog.
- Start small. One source, one or two tables, a few columns. Expand after it queries.
- Pick the kind and fill the source block (see The source block below and references/source-backends.md for per-kind config).
- Wire credentials as secrets — never inline them. Use
${secret:NAME} and declare a backend under secrets:.
- Add
examples: — one or two known-good SQL probes. They are health checks for pawrly check and hints returned to agents by describe_table.
- Validate, then probe live, then inspect the shape with
pawrly schema.
- Iterate until columns, filters, and pagination are right. Add
wiki:, cache:, safety: as needed.
Add the schema header so editors validate as you type:
version: 1
Strict keys. A typo'd or misplaced top-level field fails the load — it is not ignored. Kind-specific keys go under config: (source-level) or flat under a tables: entry, nowhere else.
The source block
sources:
- name: data
kind: file
description: "..."
wiki: |
Which filters to set, id quirks, how to decode a column.
examples:
- SELECT COUNT(*) FROM data.orders
config: { ... }
tables: [ ... ]
cache: { mode: ttl, ttl: 10m }
safety: { max_rows: 1000000 }
Only name, description, wiki, cache, safety are common across kinds; everything else is kind-specific. Split a large workspace with top-level include: ["./sources/*.yaml"].
Kind selector
| Want to query… | kind | tables: needed? |
|---|
| local Parquet/CSV/JSON | file | optional (globs auto-discover) |
| files in S3/GCS/Azure | file + storage: | required |
| a REST/GraphQL API | http | required (or config.type: openapi to synthesize) |
| another MCP server's tools | mcp | optional (tools auto-expose) |
| Postgres / MySQL | postgres/pg/postgresql, mysql | no — live catalog |
| SQLite / local DuckDB | sqlite, duckdb | optional |
| Snowflake | snowflake | no — live catalog |
| Iceberg / Delta tables | iceberg, delta/deltalake | required |
| a DuckLake catalog | ducklake | no — live catalog |
Per-kind config:/tables: keys and recipes live in references/source-backends.md. Three backends have a dedicated deep-dive page: references/http-backend.md (request/response shaping, auth styles, pagination, computed columns), references/openapi.md (synthesize tables from an OpenAPI spec), and references/mcp-backend.md (expose another MCP server's tools as tables).
Secrets
secrets:
- kind: file
path: .env
format: auto
- kind: env
- kind: keyring
service: pawrly
Reference anywhere a config: string appears: ${secret:NAME} (also ${env:NAME}, ${file:PATH}). Name secrets with a service prefix (GITHUB_TOKEN, not TOKEN).
Caching & safety (optional)
cache:
mode: ttl
ttl: 10m
safety:
require_filters_on: [order_date]
require_at_least_one_filter: true
max_rows: 1000000
max_pages: 50
timeout: 30s
required_predicates:
- "tenant_id = ${param:tenant_id}"
Mark a filter required only when the upstream truly requires it.
Authoring rules
- Prefer
snake_case, SQL-friendly, stable table names, unique within the source.
- For attach-style kinds (
postgres/mysql/duckdb/snowflake/ducklake), tables: entries do not rename or restrict the live catalog — use a semantic model for curated views (see pawrly-semantic-model).
- Verify pagination by fetching real rows across pages, not
COUNT(*).
- Keep
description capability-first ("orders, customers, refunds…"); put setup/scope detail in wiki: or secret naming, not the description.
Managing sources from the CLI
pawrly source list
pawrly source add --name gh --kind http --url https://api.github.com --token ... --set k=v
pawrly source refresh <name>
pawrly source test <name>
pawrly source remove <name>
Deliverable
Report: the config path edited, the kind chosen, validate/check/schema output, any assumptions, and any endpoint left unverified (e.g. needed live credentials).