> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cynative.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing Custom Cynative Agents: Format and Naming Rules

> Create a custom Cynative agent in one Markdown file. Covers the frontmatter schema, naming rules, shadowing behavior, and piped input handling.

One Markdown file is one agent. The filename becomes the agent name, the YAML frontmatter supplies the description shown in `agents list`, and the body is the prompt the model receives verbatim. There is no registry, no CLI command to register a file, and no build step — drop a valid `.md` file into `~/.cynative/agents/` and it is immediately available as `--agent <name>`.

## File format

Every agent file follows the same strict schema: a YAML frontmatter block with a single `description` key, followed by the prompt body.

```markdown theme={null}
---
description: Finds publicly accessible data stores in an AWS account.
---
Check S3, RDS snapshots, EBS snapshots and public AMIs for exposure.
Report each finding with the resource ARN and how it is reachable.
```

The closing `---` of the frontmatter ends the YAML block. Everything after it is the body, preserved byte for byte. A `---` line appearing in the body is body content, not a second frontmatter block. The whole file is capped at 64 KiB. The body must not be blank.

## Naming rules

The filename without the `.md` extension is the agent name. Names must satisfy all of the following:

* **Lowercase kebab-case only** — characters `a-z`, `0-9`, and `-`
* **Length** — 1 to 64 bytes
* **No leading or trailing hyphen** — `my-agent` is valid; `-my-agent` and `my-agent-` are not
* **Windows reserved names rejected on every platform** — names such as `con`, `nul`, `com1`, `lpt1` are rejected regardless of the OS you run on, so agent names are portable across environments

Examples of valid names: `aws-public-datastores`, `my-k8s-audit`, `github-review-2024`

Examples of invalid names: `AWS_Audit` (uppercase, underscore), `-leading-hyphen`, `con` (reserved), a name longer than 64 bytes

## Frontmatter rules

The frontmatter block is required and strictly validated:

* **Exactly one key: `description`** — no other keys are permitted
* **Single-line string** — newlines (including Unicode line separator U+2028 and paragraph separator U+2029) are rejected, because a multi-line description would break the `agents list` table row
* **Non-empty** — a blank description is rejected
* **At most 256 bytes**
* **No unknown keys, duplicate keys, YAML aliases, merge keys, custom tags, or multiple documents** — all fail loudly

This strictness is intentional. A key Cynative does not understand — such as a `model:` or `tools:` override — fails loudly rather than being silently ignored, so a file written against a newer version cannot appear to work while doing nothing.

## Creating your first agent

The fastest way to start is to copy a built-in and modify it:

```bash theme={null}
mkdir -p ~/.cynative/agents
cynative agents show aws-public-datastores > ~/.cynative/agents/my-aws-public-datastores.md
# edit the file, then:
cynative -p --agent my-aws-public-datastores
```

`cynative agents show` writes the exact file bytes to stdout and the source path to stderr, so the redirect captures only the file content. Open the copy in your editor, adjust the description and body to match your scope, and run it. The new agent appears in `cynative agents list` immediately — no restart or reload required.

To verify the file is valid before running a full research session:

```bash theme={null}
cynative agents show my-aws-public-datastores   # prints the file and its resolved source path
cynative agents list                            # confirms source = user and status = active
```

## Shadowing

When a file in `~/.cynative/agents/` has the same name as a built-in agent, the user file wins. `cynative agents list` marks the loser:

```
NAME                    DESCRIPTION                          SOURCE   STATUS
aws-public-datastores   My scoped version.                   user     active
aws-public-datastores   Determine which AWS managed data...  builtin  shadowed by user
```

There is no way to address a built-in that a user agent shadows. If you want to keep both, give your copy a different name.

<Warning>
  A user agent with a parsing error, an invalid name, an oversized body, a symlink target, or any file that is not a regular file is marked `invalid (blocking)` in `agents list`. It still claims the name — the run fails with an error naming the file, and resolution **never** falls through to the built-in. A typo in your own agent must fail loudly rather than silently running a different prompt that happens to share the name.

  Fix or remove the file to unblock the name.
</Warning>

## What the model receives

When you run an agent, Cynative assembles the prompt from three labelled sections in a fixed order:

```
agent description:
<the description from the frontmatter>

user instruction:
<your task, if you passed one>

agent instructions:
<the body, verbatim>
```

The `user instruction:` section is omitted entirely when you pass no task. The system prompt is unchanged — an agent is a named prompt, not a persona. Cynative's scope, halt-and-ask behaviour, and read-only rules apply exactly as they always do, regardless of what the agent's body says.

## Interactive sessions with agents

Running `cynative --agent <name>` (without `-p`) seeds the conversation with the agent's prompt as the first turn, then opens a normal follow-up session:

```bash theme={null}
cynative --agent aws-privilege-escalation
```

The first turn stays in conversation history, so the model keeps the context across your follow-up questions. The agent's instructions are not re-applied to every turn — only to the first.

One limitation: if the first turn is interrupted, stopped by the token budget, or hits the iteration limit, nothing is recorded in history, and a follow-up turn has no memory of the agent's instructions. Re-run the agent to start fresh. Sub-agents spawned by the `task` tool do not inherit the agent body — they start with a clean context by design, and the supervising model puts what they need into the task description.

## Piped input with agents

When you pipe data into a Cynative run that uses an agent, the piped bytes are always fenced in `<piped_input>` tags and treated as untrusted data to analyse:

```bash theme={null}
cat findings.json | cynative -p --agent triage-findings
```

The agent file is already supplying the instruction, so the piped bytes are data — not orders. This fencing applies even when you pass no positional task. Without an agent, bare piped stdin is treated as your task; with one, it is always data.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.