---
title: Authoring Guide
description: Write handwritten ABI YAML that stays understandable, validates
  cleanly, and is easy for agents to test and publish.
source_url:
  html: https://thru.org/docs/abi/authoring-guide/
  md: https://thru.org/docs/abi/authoring-guide.md
---

# Authoring Guide

Use this page when you are creating or editing ABI YAML by hand.

> **Caution:**
>
> Thru ABIs are handwritten today. They do not automatically stay in sync with a program, so every ABI change should be treated like real source code and validated explicitly.

## Best Starting Point

Do not start from a blank file unless you have to.

The fastest path is:

1. copy a shape from [ABI Examples](https://thru.org/docs/abi/examples.md)
2. rename packages and types
3. trim it down to the smallest schema that still represents your program
4. validate it with [ABI Analyze](https://thru.org/docs/cli-reference/abi-analyze.md)

## Authoring Priorities

| Priority | Why it matters |
| - | - |
| Stable package and type names | Codegen output and import resolution stay predictable. |
| Clear field names for counts, tags, and payloads | Reflection and generated code become much easier to use. |
| Small, reusable imported packages | Shared types stay manageable without bloating the root file. |
| Earlier size-driving fields | The resolver rejects forward references in dynamic layouts. |
| A root ABI that is easy to read | Agents can reason about the file without loading too much context. |

## What To Put In The File

At minimum, most ABIs need:

- `abi.package`
- `abi.abi-version`
- `abi.package-version`
- `abi.description`
- `types`

Program-facing ABIs often also need:

- imports for shared or on-chain types
- `options.program-metadata.root-types` so tooling knows which types are the instruction root, account root, errors, and events

## Imports

Use imports intentionally:

- `path` imports are the easiest authoring-time choice
- `onchain` imports are useful when you intentionally depend on a published ABI package
- remote imports are powerful, but they make publishing rules stricter

Practical rule:

- use local imports while you are iterating
- move to publish-safe normalization later with [ABI Prep for Publish](https://thru.org/docs/cli-reference/abi-prep-for-publish.md)

## Handwritten ABI Gotchas

- The ABI will not auto-update when the program changes.
- A valid-looking schema can still be wrong for the actual wire format your program emits or expects.
- Packing everything blindly is risky if the consumer expects alignment behavior.
- A schema can resolve successfully and still be awkward to use once you generate code from it.

## Special Note On Authorization

The ABI describes data layout. It does not describe the full authorization model of your program.

That matters most for CPI-heavy programs:

- account indices and instruction payloads may be correct
- but the callee can still fail because the authorization or account-access model is wrong

For CPI behavior, validate the program logic and SDK flow separately. The ABI only gives you the wire format.

## Best Next Step

Once the file exists, move immediately to [Validation and roundtrip testing](https://thru.org/docs/abi/validation-and-roundtrip-testing.md). That is where you prove the ABI actually matches the bytes you intend to send.
