A curated collection of Agent Skills for working with Orchestra, for agents to effectively implement standards, common workflows, and manage pipelines.
76
88%
Does it follow best practices?
Impact
100%
1.00xAverage score across 1 eval scenario
Medium
Suggest reviewing before use
Locate the script → check what it lands → fix → validate → confirm → merge/save. Narrate each step briefly, like a data engineer. Never print secrets/tokens.
MCP is preferred but optional. If the Orchestra MCP tools aren't present, use the public REST API with $ORCHESTRA_API_KEY (check the env — often already set). For git, $GITHUB_TOKEN is usually set. For schema checks you also need a warehouse credential (Snowflake/BigQuery) or S3/object-store credential — ask the user if not present.
If neither MCP nor an Orchestra key is available, point the user at the Orchestra MCP setup docs (https://docs.getorchestra.io/docs/mcp) or ask for an API key, then stop.
Base: https://app.getorchestra.io/api/engine/public — header Authorization: Bearer $ORCHESTRA_API_KEY.
identify-pipeline-error hands you: the pipeline run ID (RID), pipeline ID (PID), the failed Python task run ID (TRID), integration=PYTHON, the run branch/commit, the task's taskParameters, and the cause classification (a Python code / dependency / destination-schema issue). Use them directly — don't re-run the identification.
If invoked standalone (no handoff): run identify-pipeline-error first, or do its minimum yourself — GET /pipeline_runs?pipeline_run_ids=<RID> then GET /task_runs?pipeline_ids=<PID>&page_size=50 (filter to this RID client-side; pipeline_run_ids does not filter /task_runs, 7-day window) to find the FAILED Python task.
Capture taskParameters exactly — command/entrypoint, python_version, package_manager, requirements, branch, project_dir, and any env/run inputs. Preserve them on every retry. The pipeline run's branch is where the Orchestra YAML lives; the script's source branch (if git-backed) is a separate task param.
Pull the logs you'll fix against:
GET /pipeline_runs/<RID>/task_runs/<TRID>/logs # list filenames
GET /pipeline_runs/<RID>/task_runs/<TRID>/logs/download?filename=<file> # URL-encode spacesRead the Python traceback bottom-up: the last exception line is the real error, not the first.
You were routed here because the cause is a Python code / dependency / destination-schema issue — fix the script (and, additively, the destination shape, §4). If while reproducing you find the real cause is not that — an infra/timeout/memory problem, or a pure upstream failure (source API down, empty extract) you can't fix from here — stop and hand back to identify-pipeline-error rather than editing the script. Data/schema mismatches (the script writes a shape the destination rejects) are in scope: handle them additively in §3–4.
Python tasks come in two shapes; handle both:
branch + project_dir + a file/entrypoint): clone and reproduce locally.
git clone --depth 1 -b <branch> https://x-access-token:$GITHUB_TOKEN@github.com/<org>/<repo>.git
cd <repo>/<project_dir> && pip install -r requirements.txt
python <entrypoint> # reproduce; iterate edit → runget/list_pipelines, or the Orchestra YAML if it's stored in git). You'll fix it in the pipeline definition (Orchestra-backed → update_pipeline; or edit the inline command). State clearly to the user that this script isn't version-controlled and recommend they back it into git so it can be PR'd and CI-tested.Either way: heavy bias toward making it actually run. Edit → execute → read the next error → repeat, exactly like fixing layered dbt bugs. Don't declare it unfixable after one error; the first traceback usually masks the next.
Python tasks almost always drop data into a warehouse or S3. Before and after a fix, confirm the actual landed shape rather than trusting the script's intent.
SELECT column_name, data_type FROM <db>.INFORMATION_SCHEMA.COLUMNS
WHERE table_schema='<SCHEMA>' AND table_name='<TABLE>'; -- or DESCRIBE TABLE
SELECT COUNT(*) FROM <db>.<schema>.<table>; -- did rows actually land?Compare the columns/types the script writes against what's there. A schema-mismatch failure is the signal to evolve the destination — additively.
Bias strongly toward upward-compatible schema changes; never destroy data or shape:
ALTER TABLE ... ADD COLUMN for a new field; widen a type (e.g. INT→NUMBER, VARCHAR(50)→VARCHAR(200)); add a new partition/prefix.DROP/DELETE/TRUNCATE, no renaming/removing columns, no narrowing types, no recreating the table to "fix" it.update_pipeline (Orchestra-backed) or edit the inline command; tell the user it's not version-controlled.POST /pipelines/<PID>/start
{ "branch": "<yaml-branch>",
"continueDownstreamRun": true,
"runInputs": { ... preserve original params ... } }python → dbt → reverse-ETL/BI — the data it lands is what every downstream task consumes. A full /start (no taskIds) runs the entire DAG top-to-bottom — prefer it, because it proves dbt and downstream actually accept the new output. If you target just the failed task ("taskIds": ["<TID>"]) or use "retryFromFailed": true, you must also send "continueDownstreamRun": true, or the load succeeds in isolation while dbt/BI never re-run — and a schema change you just made (§4) goes unverified downstream.Poll GET /pipeline_runs?pipeline_run_ids=<RID> ~every 20s, one line per check:
▶ Run e2049b86 — RUNNING (0:42)
✅ Run e2049b86 — SUCCEEDED (1:44)A very-fast SUCCEEDED can be a stale first read — re-check completedAt/message. On failure, diagnose the new error (getting further is progress) and loop to §3.
Confirm the whole pipeline, not just the Python task. "Fixed" means the pipeline run is SUCCEEDED with every task green — list its task runs (GET /task_runs?pipeline_ids=<PID> filtered to the RID) and confirm none are FAILED. The most common trap: the Python load goes green but the downstream dbt task fails because it didn't expect the new/changed column — that's exactly why you run downstream (and why schema changes must be additive, §4). Then also verify the data landed (§4: row count > 0, expected columns present) — a Python task can exit 0 yet write nothing. When green end-to-end, merge the PR (or finalise the inline fix), and re-run with the original params to prove the real config works.
## Fixed: <pipeline name>
- Final run: <id> — SUCCEEDED
- Root cause: <one line>
- Fixes: <script change(s); any additive schema change with the DDL>
- Data check: <table/prefix — N rows, columns confirmed>
- PR / definition: <link or "inline, not version-controlled — recommend backing to git">/start by default; for targeted/retryFromFailed retries always add "continueDownstreamRun": true, and confirm every task in the run is green — a Python fix isn't done until the downstream dbt/BI tasks accept its output.update_pipeline; GitHub-backed need repo commits..tessl-plugin
evals
scenario-1
skills
orchestra
skills
account-health-check
references
build-data-reconciliation-pipeline
configure-dbt-build-after
configure-dbt-source-freshness
create-orchestra-pipeline
fix-orchestra-pipeline
fix-pipeline-dbt-task
fix-pipeline-python-task
identify-pipeline-error
merge-duplicate-pipelines
references
orchestra-dbt-slim-ci-setup
triage-orchestra-pipeline
write-bigquery-dq-tests
write-clickhouse-dq-tests
write-databricks-dq-tests
write-snowflake-dq-tests