Agents

"For agents: Myna in one page"

A dense operating manual for agents working against a Myna project, suitable for pasting into AGENTS.md or CLAUDE.md.

Myna is a platform of products a project enables:

  • Content — schemas are code, all writes create draft revisions grouped into change sets, and publishing is a separate, human-gated atomic operation. You draft, validate, and preview; a human reviews field-level diffs and publishes.
  • Analytics — page views and custom events, with sessions, funnels, and the joins to content and reports. You read; the only thing you write is what an event means.
  • Feedback — bug reports and QA findings on boards, with an append-only timeline. You read, reproduce, reply, and resolve.

The three are the point. Content is what the product says, Analytics is what people did, Feedback is what they said — and because they share a project, "why did signups drop this week" is a sequence of calls rather than a research project.

A route or tool belonging to a product the project does not run answers PRODUCT_NOT_ENABLED — a 404. Do not retry it with different arguments.

Credentials

  • API keys are bearer tokens with the prefix myna_sk_. Send Authorization: Bearer $MYNA_TOKEN.
  • SDK/CLI/MCP all read MYNA_TOKEN; the MCP server also reads MYNA_PROJECT, MYNA_ORGANIZATION, and MYNA_API_URL (default https://api.myna.sh).
  • Your key is typically scoped content:read, content:write, assets:read, assets:write, preview:write, schema:read, plus feedback:read, feedback:write, and analytics:read — and deliberately not content:publish. See scopes.
  • project:admin never widens to a product added later. A key that should reach every product needs admin:all by name.

The golden rules

  1. Writes are drafts. Creating or updating an entry never changes what is publicly served.
  2. Never publish without explicit human instruction. Even if you hold content:publish, do not call publish unless the human asked for it in this task.
  3. Always create a preview. End every writing task with one preview URL covering the whole change set, and hand it to the human.
  4. Include changeSummary on every write. One sentence per change; reviewers read these like a commit log.
  5. Use expectedRevisionId when updating an existing entry, so concurrent edits fail loudly (STALE_REVISION) instead of being clobbered.
  6. Destructive MCP tools require confirm: true: myna_delete_entry, myna_unpublish_entry, myna_publish_change_set, myna_schedule_change_set, myna_close_change_set, myna_restore_revision, myna_revert_release, myna_reorder_entries.
  7. Read the guidance. myna_get_collection_schema returns a guidance string when the collection has one — the project's house style for what you are about to write. Follow it; it is the part a schema cannot express. It also returns policy: the rules the collection enforces, which fail the policy check and block publishing if you break them.
  8. Check for company before writing. myna_get_entry returns openChangeSets — anyone else already staging a change to this entry, and the fields they touch — plus contendedFields where more than one does. A collision found here is free; the same collision found by the conflicts check costs whatever you wrote first.

Content: the loop

MCP tool names (see the tool reference) with CLI equivalents:

  1. myna_search_entries — find the entry a human described in prose ("the pricing page") instead of listing a collection and scanning it. Full-text over every text field, draft or published. CLI: $ myna entries search "<words>".
  2. myna_get_collection_schema — know the fields and the guidance before writing. CLI: $ myna schema inspect <collection>.
  3. myna_create_change_set — one change set per task. Check myna_list_change_sets first if you may be resuming work. CLI: $ myna changes create --title "...".
  4. myna_create_entry / myna_update_entry — pass changeSet, changeSummary, and (on update) expectedRevisionId. On an update, myna_get_entry first: its openChangeSets says whether someone is already editing the fields you are about to touch. CLI: $ myna entries create <collection> --set k=v --change-set chs_... --summary "..." and $ myna entries update <collection>/<slug> --set k=v --expected-revision rev_... --change-set chs_... --summary "...".
  5. myna_upload_asset — base64 bytes or a local path. CLI: $ myna assets upload <path>.
  6. myna_validate_change_set — fix every reported error before previewing. CLI: $ myna changes validate chs_... (non-zero exit when invalid).
  7. myna_diff_change_set — read back what you actually changed, field by field, and use it to write your summary. Long prose fields carry word-level segments, so a body you rewrote reads as the words that moved. CLI: $ myna changes diff chs_....
  8. myna_create_preview — exactly one of changeSet or entry; prefer the change set. CLI: $ myna changes preview chs_....
  9. Stop. Report the change set id and preview URL. Publishing (myna_publish_change_set with confirm: true; CLI $ myna changes publish chs_... --confirm-publish) is for humans or explicitly instructed, publish-scoped principals. It applies the whole change set in one transaction.

Entries are addressed as <collection>/<slug> or by ent_ id. Statuses: draft, published, changed, unpublished, deleted.

If a task is cancelled, close your change set (myna_close_change_set) rather than leaving it open. Abandoned sets accumulate and every one of them looks to a human like work waiting for review.

Beyond the loop

  • Reuse assets. myna_list_assets accepts a checksum; check before myna_upload_asset so the same logo does not land three times. If you upload anyway, the result's similar names existing images that look like the same picture — including resized or re-encoded copies a checksum cannot match. Reference one of those and delete your upload rather than leaving the library with two. myna_update_asset sets alt text, which the policy check requires wherever a collection declares policy.altText().
  • Bulk work. myna_import_entries creates and updates many entries in one call, matched by slug, with dryRun: true to see what would happen first. Prefer it over a hundred single writes.
  • Reviewing. myna_diff_change_set plus myna_get_change_set_review is everything a reviewer sees. If the project declared an external check you can compute, report it with myna_report_check_result; a failing required check blocks publish, so do not report passed you did not verify.
  • Translations. myna_translation_coverage names exactly which entries and fields are missing a locale.

Feedback: the loop

The fourteen Feedback tools exist only when the project runs Feedback. In the order they are usually needed:

  1. myna_report_digest — what came in since a time or a release, counted and ordered by priority. One call rather than paging myna_list_reports. CLI: $ myna feedback digest --since <iso>.
  2. myna_get_report — the description, the environment the application supplied, the board's guidance, every custom field, the whole timeline, and what evidence exists. CLI: $ myna feedback reports open 42.
  3. myna_get_report_attachment — images come back as images you can look at. CLI: $ myna feedback attachments get 42 rat_... --out shot.png.
  4. myna_find_similar_reports — check for a duplicate before spending a reproduction on one.
  5. myna_update_report — status, priority, assignee, labels, title, body, in one call.
  6. myna_reply_to_reportvisibility defaults to internal. Pass "public" only when you mean to reach whoever filed the report.
  7. myna_resolve_report — resolve, link the commit or pullRequest, and reply in one call. Set requestRetest: true when you could not reproduce the problem yourself: it asks the reporter to confirm rather than declaring the matter closed. myna_request_retest does the same for a report you are not resolving.

Reports are addressed by per-project number, so #42 works anywhere an id does. Statuses: triage, open, in_progress, needs_retest, resolved. The timeline is append-only — a resolution can be reopened and a merged duplicate keeps its own history, so nothing you do here destroys the record.

Read the board's guidance the way you read a collection's: it is the house style for handling reports there, and reporters never see it.

myna_merge_report marks a duplicate; nothing is deleted, so a wrong merge buries a distinct problem rather than losing it. myna_move_report moves a report to another board on the same project — every board is read by the same people, so that is filing, not publishing.

Blocking a reporter is not triage. myna_block_reporter exists for abuse, not for somebody who reports too much. It stops them filing, reading their reports back, and being emailed.

Analytics: answering "what changed"

The ten Analytics tools exist only when the project runs Analytics. Read them in this order when somebody asks why a number moved.

  1. myna_analytics_events first, always. It lists every event the project records and what each one means. Nothing in the data says whether checkout_started fires on the click or on the page, and a funnel built on the wrong assumption is confidently wrong. If an event you need is undescribed, describe it with myna_describe_analytics_event once you have worked out what it measures — that is a durable contribution, not a side effect.
  2. myna_analytics_overview — the window, the previous window, and the change, in one call. Enough to say whether anything is different.
  3. myna_analytics_friction — where people stop: exit pages, bounce pages, and the pages generating bug reports out of proportion to their traffic. The third list is the one to start from, because it names a page and tells you what people said about it.
  4. myna_analytics_breakdown — narrow it. Any dimension, or property:<key> for a custom property. entry, collection, and release group by Myna content.
  5. myna_analytics_funnel — ordered, time-bounded conversion. Order is enforced, and withinHours runs from the visitor's first step.
  6. myna_analytics_release_impact — the payoff. Give it a release number and it returns overall movement, per-entry movement for everything the release touched, per-event movement, and the reports filed since. It is correlation: say so when you report it. A release is not the only thing that happened that day.
  7. myna_analytics_entry — one content entry: its numbers, every publication in the window, and what moved either side of each.
  8. myna_analytics_person — one user's sessions, events, and reports together. When a report is hard to reproduce, the events before it are usually the steps the reporter did not write down.

Every read takes the same filters and echoes back the window it resolved, so a number you quote can be reproduced. Name either period (7d, 30d) or from/to — naming both is refused rather than guessed at.

Then close the loop with the Content tools: a change set fixing what you found, validated and previewed, published by whoever holds content:publish. Myna collects the ground truth; the reasoning and the fix are yours.

When a call fails

myna doctor --json reports the CLI version, API reachability and compatibility, whether the credential is valid, which scopes the key carries, project access, and schema drift — each with a status and a remedy. Check it before retrying a failing call or reporting a broken setup.

A denial can mean a missing scope or a missing resource. myna auth verify --json returns credentialPresent and credentialValid separately, so a stored-but-rejected credential is distinguishable from one that was never there.

After a 403 or 404, call myna_explain_denial once instead of retrying. Pass the tool that failed (and the collection it touched, if any); it names which of three unrelated causes applies — the credential lacks the capability, the credential is confined to other collections, or the resource does not exist — and returns a remedy. Only the last is worth another attempt with different arguments; the first two are worth reporting to a human, because no retry will change them. CLI: $ myna access --capability content:publish --collection posts (exit code 1 when denied).

Where to learn more

  • https://docs.myna.sh/llms.txt — index of all docs; llms-full.txt is the full concatenation.
  • Append .md to any docs URL for raw Markdown (e.g. /concepts/change-sets.md).
  • https://docs.myna.sh/openapi.json — OpenAPI 3.1 description of the HTTP API.

Common errors

Code HTTP What to do
VALIDATION_FAILED 422 Read the per-field errors, fix the offending fields, retry the write.
STALE_REVISION 409 Someone else wrote first. Re-read the entry, merge, retry with the new expectedRevisionId.
PERMISSION_DENIED (on publish) 403 Expected: your key lacks content:publish. Stop and ask the human to review the preview and publish.
PLAN_LIMIT_REACHED 402 Stop and report; the organization's plan limit must be raised by a human.
PERMISSION_DENIED (naming collections) 403 Your key is confined to specific collections. The message lists them; work within it and report the mismatch rather than trying another route.
CHECKS_FAILED 409 A required check has not passed on the current contents. Fix what it reports, or report the check result if you are the one computing it.
PRODUCT_NOT_ENABLED 404 The project does not run that product. enabledProducts lists what it does run. No retry helps; report it.

Every mutation you make is attributed (created_by_type, created_by_id) and every revision is immutable — you cannot destroy history, so prefer acting and reporting over asking about safe, draft-level operations.