Format package rules: skill_path_invalid, file names, and limits
What a Format package may contain over the Contents API: SKILL.md name equals slug, two directories, a file-name pattern, five extensions, and 1000 paths.

A commit to a Format package is rejected with skill_path_invalid when a path breaks the rules: SKILL.md is required at the root with a frontmatter name equal to the Format's slug, files sit at the root or one level under references/ or agents/, names match ^[A-Za-z0-9][A-Za-z0-9._-]*$, and only five extensions are allowed.
The rules are from Editing a Format package, read on 2026-10-02. They are the same ones the dashboard editor enforces, and a package that breaks any of them is rejected before anything is committed.
What are the exact rules?
Check your paths against this before you send a batch.
| Rule | Value |
|---|---|
| Required file | SKILL.md at the root; cannot be deleted |
| SKILL.md frontmatter | name must equal the Format's slug |
| Directories | Root, or one level under references/ or agents/ |
| Path | No .. and no absolute paths |
| File name | Matches ^[A-Za-z0-9][A-Za-z0-9._-]*$, so no leading _ or . |
| Extensions | md, json, yaml, yml, txt |
| Size | At most 100 MiB per file and per package |
| Batch | At most 1000 paths in one commit |
What does the error tell me?
A rejected path answers with skill_path_invalid and spells the whole allowlist back, so the first rejection is enough to fix the name. Related 400 codes are skill_frontmatter_invalid and skill_limit_exceeded.
A rejected batch commits nothing. Batches land whole or not at all, so a single stale sha or bad path in a list of ten files leaves the Format exactly as it was.
Why does my commit fail with a conflict instead?
Conflicts are 409, not 400. format_content_sha_required means the path exists and you sent no sha. format_content_sha_mismatch means your sha is stale. format_package_sha_mismatch means your If-Match package sha is stale, and error.details.package_sha holds the current one.
How do I commit a valid change set?
PUT at the package root takes a files list and writes one commit. Paths you do not name are kept as they are, and deletion is not expressible in this call. Use DELETE on a path for that.
curl -sS -X PUT \
"https://api.sume.com/v1/formats/acme/live-commerce/contents" \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "add a facts note",
"files": [
{ "path": "references/facts.md", "content": "IyBGYWN0cwo=" }
]
}'What does this surface not do?
There is no public git endpoint and no clone URL. Reverting, blame and history browsing are not part of this surface yet. Editing a package never touches a run already in flight, since each run reads the package it started with.
Examples of paths that fail
Edit locally, check names against the pattern, and commit as a single change set so a mistake costs nothing.
_draft.mdfails because file names cannot start with_.notes/plan.mdfails because the only subfolders arereferences/andagents/.references/deep/plan.mdfails because directories go one level deep.references/plan.pdffails because only md, json, yaml, yml and txt are allowed.SKILL.mdwithname: promo-v2in a Format whose slug ispromofails the name rule.
How do I read a package before editing?
GET .../contents?recursive=1 returns every file with its body and sha, sorted by path, with no directory rows. That one read is enough to start editing, because each row's sha is the precondition a write takes.
Keep the package_sha (the commit.tree.sha of your last write) for the If-Match header. If another agent moved the package on, you get 409 format_package_sha_mismatch with the current sha in error.details, and can re-read and retry in one round trip.
Is the dashboard editor the same?
Yes. The docs say these are the rules the dashboard editor enforces, so a package you build over the API and one you build by hand follow one set of rules. The commit's author is always the key's owner; an author or committer in the body is ignored.
Reads need formats:read and writes need formats:write. Service-account keys cannot create or edit packages.
Sources
Related posts
More in Formats
- Format reads inactive but still runs: the 409 codes
A never-run Format may read inactive until its first API run. The real refusal is a 409 format_inactive or format_api_trigger_disabled.
- Format run agent_reported_failure vs deliverable_missing: retry or not
agent_reported_failure means the run said it did not deliver; deliverable_missing means it made no media at all. Both leave a failed run, but the retry differs.
- The built-in Format output schema: sume/action-run-output/v1
No output_schema on a Format run returns sume/action-run-output/v1: text plus four media arrays, filled without a model, so it cannot fail like a custom schema.
- Format run failed provider_unavailable or mcp_unavailable: retry rules
provider_unavailable and mcp_unavailable are Sume-side Format run failures: retry with a new Idempotency-Key. provider_credits_exhausted waits.
Written by Sume