agentsclimarketplace

Customs query

Skill FrancoisChastel/sydonia-toolkit/skills/customs-query

Write friendly SQL, compile it to genuine ASYCUDA World (SYDONIA) customs SQL you can run read-only. A fully-sourced PostgreSQL reference model + query compiler + docs + Agent Skills for customs analytics, ML & selectivity.

Install
npx -y skills add FrancoisChastel/sydonia-toolkit --skill customs-query

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 21 days oldThe repository was created 21 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Generate correct SQL against the Sydonia Toolkit ASYCUDA / SYDONIA customs model — reports, lookups, reconciliations, analytics — and verify it privacy-preservingly. Knows the `asycuda` schema search_path, that coded columns are foreign keys to ref_* tables, that totals are derived (not stored), and the canonical join paths (declaration → item → tax line; manifest → bill of lading → cargo). Can test/validate generated queries via the customs-query-tester MCP (or a bundled script): metadata only, never row data — safe against databases holding real customs declarations. Can also COMPILE a logical query into genuine ASYCUDA World SQL (SAD_General_Segment, SAD_Tax…) to run on a real Sydonia database. Use when the user asks for a query, report, or number from the customs / declaration / manifest data, wants a query checked/tested/validated, or wants to run it against a real Sydonia.

SKILL.md

6.4 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it

Customs query

Turn a plain-English question about the customs data into a correct PostgreSQL query — then prove it runs without exposing any row data. The model is normalised, so two rules govern almost everything.

Two rules to always apply

  1. Set the search path. Every table is in the asycuda schema:
    SET search_path TO asycuda, public;
    
  2. Coded columns are foreign keys. To show a code's name, join its ref_* table (e.g. d.declaration_type_id → ref_declaration_type). Totals like "total tax" are derived by aggregation, not stored — sum declaration_tax_line.tax_amount.

The model map

Two spines carry most queries:

manifest → bill_of_lading → container / manifest_cargo_item      (cargo)
declaration → declaration_item → declaration_tax_line            (declaration)
                             ↘ item_value_note (per-item CIF)

Key tables by intent:

Want…Start from
Declarations, parties, regime, status, lanedeclaration (+ ref_*, trader)
Line items, HS codes, customs valuedeclaration_item
Duty/VAT/excise per linedeclaration_tax_line (+ ref_tax_type)
Manifests, voyages, bills of lading, cargomanifest, bill_of_lading, manifest_cargo_item
Payments, receipts, accountspayment, receipt, account
Risk lanes, inspectionsselectivity_result, inspection_act, ref_selectivity_lane
Lifecycle historydeclaration_status_history (+ ref_declaration_status)

Workflow: generate, then verify

  1. Generate. Identify the spine and the ref_* joins; adapt the closest annotated query in reference/cookbook.sql (declaration assembly, items-with-taxes, cargo listing, assessed-vs-paid, revenue by HS/tax, lane throughput, write-off tracing, warehouse stock) rather than starting from scratch. Aggregate for totals; add ORDER BY.

  2. Verify — privacy-preservingly. Never verify by SELECT-ing rows: the target database may hold real customs declarations (TINs, values, findings), and the user's data must not enter the conversation.

    Preferred — the customs-query-tester MCP (if its tools are available, possibly via ToolSearch):

    • describe_schema — check a table/column you are unsure of.
    • validate_query {sql} — EXPLAIN-only: syntax + references, no execution.
    • test_query {sql} — runs it read-only and time-boxed; returns column names/types, row count, duration only.

    Fallback — the bundled script (relative to this skill's folder; same guarantees through plain psql):

    bash scripts/test_query.sh "SELECT ..."
    # env/flags: CUSTOMS_DB / --db · CUSTOMS_SCHEMA / --schema (defaults: customs_sandbox / asycuda)
    
  3. Iterate on errors. A failed validate/test returns the PostgreSQL error — fix the query, not the guardrails. If a table seems missing, check describe_schema / Sydonia/DATA_DICTIONARY.md before inventing columns.

  4. Deliver. Hand the user the final query (with SET search_path) and report the verification result — e.g. "valid; returns 42 rows, 5 columns, 0.2 s". Do not run the query unguarded to show sample rows unless the user explicitly asks you to display their data.

Run it on a real Sydonia — compile to genuine SQL

The queries above use the toolbox's friendly logical names. A real ASYCUDA World database is wide and denormalised with different names (SAD_General_Segment, SAD_Tax.AMT, TAR_HSC_NB1..5…). To run the same logical query there, compile it — don't rewrite it by hand:

  • MCP: compile_query {sql, test?} — returns genuine ASYCUDA World SQL; with test: true it also runs it read-only (metadata only).
  • Fallback: bash scripts/compile.sh --test "SELECT ... FROM declaration ..."

The compiler (compiler/) wraps the friendly names in a CTE prelude over the real tables and bakes in the gotchas (INSTANCE_ID, general-segment repetition, HS split, validity dates). Pin your instance's real column names with a per-instance overrides file (--overrides, env CUSTOMS_OVERRIDES). Develop against customs_sandbox (logical), then compile and test against the real DSN — always read-only. See compiler/README.md.

Privacy rules (non-negotiable)

  • Verification returns metadata only: columns, types, row count, timing.
  • Sessions are read-only (default_transaction_read_only=on) with a statement timeout — enforced by both the MCP server and the script.
  • Only single SELECT/WITH statements are ever sent to be tested.
  • Never bypass the tester with raw psql -c "SELECT …" to "peek" at data.

Explore when unsure

SET search_path TO asycuda, public;
\d+ declaration          -- columns, types, FKs of one table
\dt                      -- all 55 tables

The full column reference is Sydonia/DATA_DICTIONARY.md; the MCP's describe_schema gives the same, live.

Pitfalls

  • Forgetting the search_path → "relation does not exist". Set it first.
  • Selecting a *_id and expecting a label → join the ref_* table.
  • Summing tax_base instead of tax_amount for revenue.
  • VAT cascades (its base includes duty) — don't re-derive tax; read declaration_tax_line.
  • Money is numeric(18,4); don't cast to float for reporting.
  • count(*) differing from expectations on LEFT JOINs — check fan-out on the tax-line join before aggregating.

Gives 0 of the 12 instructions most databases sql skills give in ~1.4k tokens

Counted across 589 of the 662 authors here whose files we hold, read 2026-08-06

  • use parameterized queriesin 36 of 589, across 32 files
  • use timestamptz for timestampsin 30 of 589, across 12 files
  • create indexes concurrentlyin 29 of 589, across 23 files
  • index foreign keysin 28 of 589, across 17 files
  • use numeric type for moneyin 25 of 589, across 8 files
  • select only required columnsin 24 of 589, across 19 files
  • use cursor pagination instead of OFFSETin 23 of 589, across 15 files
  • add indexes manually on foreign key columnsin 22 of 589, across 11 files
  • read individual rule files for detailed explanationsin 18 of 589, across 4 files
  • configure connection poolingin 18 of 589, across 16 files
  • put equality columns before range columns in indexesin 17 of 589, across 9 files
  • normalize to third normal formin 17 of 589, across 8 files

Said here and by no other author read

  • set the search_path to asycuda
  • join ref_* tables for coded column names
  • aggregate tax_amount for totals
  • adapt queries from the cookbook
  • verify queries using the tester
  • iterate on errors by fixing the query

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.