Morphic Agent Framework

reference

Cross-cutting material that governs how work is done, regardless of where.

export reference Voice:
    description: How the product speaks to users.

    guidance:
        Plain and direct. Never cute. Name the object, not the gesture:
        "Delete layer", not "Remove this".

A reference is a rule that applies everywhere.

The other four definition kinds partition your software: the concept is the whole, domains are regions, components and features are things inside them. A reference cuts across all of it. Voice. Naming. Error style. Commit conventions. How your API is shaped.

It is the catch-all, and it is also — line for line — the highest return of anything in Morphic, because these are the rules you have already explained out loud several times.

guidancestring, required

The rule, and enough of it to apply.

The failure mode here is abstraction. "Be consistent." "Write clear errors." "Keep the API simple." Those are not rules, they are agreements to have the argument later, and an agent handed one will produce something it can defend and you will not like.

Write rules you could be wrong about. Then give examples.

# No. Nobody disagrees, and nobody can act on it.
guidance:
    Error messages should be clear and helpful.

# Yes. This decides things.
guidance:
    Say what happened, then what to do about it, in that order. One sentence
    each.

    Name the thing that failed, not the layer that noticed. "Could not read
    config.psy" — not "FileSystemAdapter threw".

    Never show a stack trace to an end user. Log it, and give them an id.

Examples, in pairs

The single most effective thing you can put in a reference is a good/bad pair. They are unambiguous, they are short, and they do not require the reader to share your taste.

export reference Voice:
    description: How the product speaks to users.

    guidance:
        Plain and direct. Never cute, never apologetic, never chatty.

        Name the object, not the gesture. Users think about the thing they are
        acting on, not the act.

    examples:
        - "Delete layer" — not "Remove this"
        - "Export failed. The disk is full." — not "Oops! Something went wrong :("
        - "3 layers selected" — not "You have selected 3 layers"

    avoid:
        - Exclamation marks
        - "Please" and "Sorry"
        - Naming our own internals in user-facing text
---
name: voice
description: "Reference: How the product speaks to users."
---

# Voice

## Guidance

Plain and direct. Never cute, never apologetic, never chatty.

Name the object, not the gesture. Users think about the thing they are acting
on, not the act.

## Examples

- "Delete layer" — not "Remove this"
- "Export failed. The disk is full." — not "Oops! Something went wrong :("
- "3 layers selected" — not "You have selected 3 layers"

## Avoid

- Exclamation marks
- "Please" and "Sorry"
- Naming our own internals in user-facing text

## Authority

This describes the product as it is meant to work. Where the implementation
disagrees, treat this as correct unless the task is explicitly to change it.

examples and avoid are not properties Morphic knows about. They became sections anyway.

Examples

Naming conventions

use "@psy/morphic"

export reference Naming:
    description: Naming conventions across the codebase.

    guidance:
        Types are nouns. Functions are verbs. Anything that mutates the
        document is a Command and its name ends in one.

        Prefer the domain's word over the general one. We have layers, not
        elements; anchors, not points; a canvas, not a viewport.

    examples:
        - `MoveLayerCommand` — mutates, so it is a Command
        - `flattenLayers()` — a verb, does not mutate
        - `LayerStack` — a noun, and the domain's word

    avoid:
        - `Manager`, `Helper`, `Util`, `Service` as name suffixes. They mean "I could not decide what this is."
        - Abbreviations that are not already in the glossary
---
name: naming
description: "Reference: Naming conventions across the codebase."
---

# Naming

## Guidance

Types are nouns. Functions are verbs. Anything that mutates the document is a
Command and its name ends in one.

Prefer the domain's word over the general one. We have layers, not elements;
anchors, not points; a canvas, not a viewport.

## Examples

- `MoveLayerCommand` — mutates, so it is a Command
- `flattenLayers()` — a verb, does not mutate
- `LayerStack` — a noun, and the domain's word

## Avoid

- `Manager`, `Helper`, `Util`, `Service` as name suffixes. They mean "I could
  not decide what this is."
- Abbreviations that are not already in the glossary

## Authority

This describes the product as it is meant to work. Where the implementation
disagrees, treat this as correct unless the task is explicitly to change it.

The Manager/Helper/Util line is the sort of thing that would otherwise be a review comment every few weeks, forever.

API conventions

export reference ApiConventions:
    description: How our HTTP APIs are shaped.

    guidance:
        Resources are plural nouns. Actions that do not fit CRUD are a POST to
        a sub-resource, not a verb in the path.

        Every list endpoint is paginated from day one, cursor-based, even when
        the collection is small today.

        Errors return a stable machine-readable code alongside the human
        message. Clients switch on the code; the message is for logs.

    examples:
        - `POST /invoices/{id}/void` — not `POST /voidInvoice`
        - `GET /customers?cursor=…&limit=…` — never offset pagination
        - `{ "code": "invoice_already_paid", "message": "…" }`

    avoid:
        - Verbs in paths
        - 200 with an error body
        - Breaking a response shape without a version

Testing style

export reference TestingStyle:
    description: How tests are written here.

    guidance:
        A test names the behaviour, not the function. If the function is
        renamed the test name should still read correctly.

        Assert on observable behaviour, never on internal calls. A test that
        breaks on a refactor with no behaviour change is a bug in the test.

        One reason to fail per test.

    examples:
        - `it("keeps layer order across save and load")` — not `it("tests LayerStack.save")`

    avoid:
        - Mocking anything you own. Mock the network and the clock; nothing else.
        - Snapshot tests of anything a human has not read

Visual language

export reference VisualLanguage:
    description: Spacing, colour and type across the interface.

    guidance:
        Spacing is a 4px scale. Nothing is ever an arbitrary pixel value.

        Colour is semantic, never literal: `--surface-raised`, not
        `--grey-200`. A component that names a literal colour has taken a
        decision that belongs to the theme.

        Two type sizes per panel, maximum.

    avoid:
        - Hard-coded hex values outside the theme definition
        - Shadows for anything other than elevation

Extra properties that earn their place

PropertyUse it for
examplesgood/bad pairs — add these before anything else
avoidthe specific things you keep having to reject
rationalewhy, when the rule looks arbitrary
exceptionswhere the rule genuinely does not apply
---
name: api-conventions
description: "Reference: How our HTTP APIs are shaped."
---

# ApiConventions

## Guidance

Resources are plural nouns. Actions that do not fit CRUD are a POST to a
sub-resource, not a verb in the path.

Every list endpoint is paginated from day one, cursor-based, even when the
collection is small today.

Errors return a stable machine-readable code alongside the human message.
Clients switch on the code; the message is for logs.

## Examples

- `POST /invoices/{id}/void` — not `POST /voidInvoice`
- `GET /customers?cursor=…&limit=…` — never offset pagination
- `{ "code": "invoice_already_paid", "message": "…" }`

## Avoid

- Verbs in paths
- 200 with an error body
- Breaking a response shape without a version

## Authority

This describes the product as it is meant to work. Where the implementation
disagrees, treat this as correct unless the task is explicitly to change it.

exceptions matters more than it looks. A rule with no stated exceptions gets applied in the one place it should not, and because definitions are normative, applied confidently.

    exceptions:
        - Generated files are exempt from the naming rules. They are output, not source.

reference or skill?

This is the one real point of confusion in Morphic, and it is worth being precise about, because both are prose telling somebody how to do something.

referenceskill
Isknowledge about the productinstructions for working
Answers"what are the rules here?""how do I do this task?"
Named bycontextuse
Voicedeclarative — errors name the thing that failedimperative — read the whole diff first
Changes whenthe product's conventions changeyour process changes
Inheritsauthority — it is normativenothing like it

The rule of thumb: if it would still be true with no AI agent anywhere near the project, it is a reference. Your error message style is a fact about your product. "Read the whole diff before commenting" is a fact about how you would like work done.

Getting it wrong is not catastrophic — both render as loadable skills — but it puts the rule in the wrong place, so it churns for the wrong reasons and gets loaded at the wrong times.

When to write one

The moment you have explained something for the second time.

That is the whole heuristic and it works better than any taxonomy. A rule you have explained twice is a rule you will explain twenty times. Writing it down as a reference takes ten minutes and it is the only definition kind that pays for itself immediately.

References are also the best place to start on an existing codebase, because they require no architectural analysis — just recall of the last few code reviews. See Specifying Software.

When not to write one

  • For a rule that applies to one area. That is an invariant on the domain or the component.
  • For instructions to an agent. That is a skill.
  • For something universally agreed. "Write readable code" is not a rule, it is a mood.

How it renders

---
name: voice
description: "Reference: How the product speaks to users."
---

# Voice

## Guidance

Plain and direct. Never cute, never apologetic, never chatty.

Name the object, not the gesture. Users think about the thing they are acting
on, not the act.

## Examples

- "Delete layer" — not "Remove this"
- "Export failed. The disk is full." — not "Oops! Something went wrong :("

## Avoid

- Exclamation marks
- "Please" and "Sorry"
- Naming our own internals in user-facing text

## Authority

This describes the product as it is meant to work. Where the implementation
disagrees, treat this as correct unless the task is explicitly to change it.

Wire it to whatever it governs:

export skill WriteInterfaceCopy:
    description: Write or revise user-facing text.
    when: Use when adding or changing any string a user will read.

    context:
        - Voice

    prompt:
        Write the copy, then read it back as though you were annoyed and in a
        hurry. Cut anything that does not survive.

Next: What Gets Generated

On this page