---
name: fontana-agent-authoring
description: Write a Fontana agent package folder (AGENT.md, optional schedules.json and avatars/) for upload on AI → Agent packages. Use when asked to create, draft, or export a Fontana agent, persona, or AGENT.md.
---

# Fontana agent authoring

You write a folder on disk. The operator uploads that folder with **Upload folder** on **AI → Agent packages** (`/ai/agents`). Fontana registers every `AGENT.md` it finds and, when present, the sibling `schedules.json`.

Operator guide: `https://fontana-ai.com/docs/ai/author-agents/`
This skill: `https://fontana-ai.com/docs/ai/agent-authoring-skill.md`

## What you produce

One package directory. Its name is the agent slug: lowercase, hyphenated, no spaces. `AGENT.md` sits directly inside that directory.

```text
nav-analyst/
├── AGENT.md            # Required
├── schedules.json      # Optional shared schedules
└── avatars/
    └── avatar.png      # Optional; frontmatter icon points here
```

After upload into a namespace the operator chooses, the agent id is `<namespace>/<folder>`. Example: namespace `finance` plus this folder is `finance/nav-analyst`.

Upload into a namespace the operator created. Fontana's own agents live in `system`. When a `default` namespace is still present, leave that one alone as well.

The folder path is the identity. Frontmatter omits `id` and `name`. A file that includes either key fails ingest.

## AGENT.md

The file starts with a YAML frontmatter block (`---` on the first line, closed by `---`) and continues with a Markdown system prompt. An empty body fails ingest.

### Keys ingest accepts

| Key | Required | What to write |
| --- | --- | --- |
| `title` | Yes | Display name in chat |
| `description` | Yes | One- or two-sentence catalog summary |
| `vectorSource` | Yes | Keywords for routing: role, domain nouns, deliverable names |
| `role` | No | Short job title, for example `NAV analyst` |
| `model` | No | Approved model id, or `""` for the deployment default |
| `scopes` | No | Where the agent can be picked. Omitted means `[chat]` |
| `skills` | No | Map of catalog id to settings. Presence enables that ability or skill |
| `permissions` | No | Allow-list. Omitted means `["*"]` |
| `isActive` | No | `true` for a package the operator can pick |
| `reasoningEffort` | No | `none`, `minimal`, `low`, `medium`, `high`, or `xhigh` |
| `callSettings` | No | Mapping of model call fields (see below) |
| `voice` | No | Voice catalog id `provider::voiceKey`, only when the operator asked for speech |
| `icon` | No | Package-relative path under `avatars/`, or inline SVG |
| `accentColor` | No | One of `orange`, `amber`, `yellow`, `lime`, `green`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `pink`, `rose`, `slate` |
| `contextTokenLimit` | No | Token count, a digit string, or a percent such as `"75%"` |
| `contextCompressTargetTokens` | No | Same shapes as `contextTokenLimit` |
| `contextMinRecentUserMessages` | No | Positive integer |
| `contextToolResultRounds` | No | Positive integer |
| `contextKgBodyTurns` | No | Positive integer |

Leave context keys out unless the operator asked for a custom context budget.

### Scopes

`chat`, `workflow` (AI node), `kg-extract` (Knowledge Graph extract), `eval` (eval judge), `icon`, `internal` (background worker, hidden from pickers).

A new package uses `chat` unless the operator named another surface. `icon` and `internal` are for workers Fontana calls itself.

An explicit `scopes` list contains at least one of those values.

### Skills and abilities

`skills` is a mapping. The key is a catalog id (`namespace/package`). The value is that package's settings, plus optional `autoLoad: true` when this ability must be present on the first turn.

```yaml
skills:
  system/knowledge-graph: {}
  system/agents:
    agents:
      - system/fontana-agent
```

`system/knowledge-graph` auto-loads on its own. Set `autoLoad: true` only for the agent's primary job. An auto-loaded package costs its tools and instructions on every turn.

A conversational agent includes `system/agents` with `system/fontana-agent` in `agents`, so Fontana product and navigation questions hand back to that agent. `agents: ["*"]` allows every active agent.

Enable only what the job needs. The operator can turn more on in the editor.

| Catalog id | Settings you may set |
| --- | --- |
| `system/knowledge-graph` | `namespaces` (list of Knowledge Graph namespace names), `autoSearchKg` (boolean), `kbInjectionScoreThreshold` (number, platform default 0.35) |
| `system/agents` | `agents` (agent ids, or `*`) |
| `system/workflows` | `autoSearchWorkflows` (boolean). This ability is the Projects surface |
| `system/email` | `allowReceive`, `allowSend` (booleans), `receiveWhitelist`, `sendWhitelist` (lists of address patterns) |
| `system/messaging` | Slack. `messagingWhitelist` (channel names or ids), `slackInstallationId`, `toolSubset` |
| `system/teams` | `channelWhitelist`, `freeResponseChannels`, `requireMentionInThread`, `allowBots` |
| `system/coding` | `toolSubset` |
| `system/fontana-browser` | `toolSubset` |
| `system/files`, `system/data`, `system/agent-memory`, `system/workflow-documents`, `system/system-one` | `{}` |
| `system/mcp-<slug>` | `{}` or `toolSubset`, for an MCP connection that already exists in the workspace |

Operator-authored skills use the same map: `acme/month-end: {}`. Page abilities (`system/dashboard-pages` and the other `*-pages` packages) belong to Fontana's own page agent. Leave them off a specialist you are writing.

These frontmatter keys were replaced by the abilities above. A file that still contains one fails ingest: `tools`, `subagents`, `handoffAgents`, `knowledgeGraphNamespaces`, `autoSearchKg`, `autoSearchWorkflows`, `kbInjectionScoreThreshold`, `emailSendWhitelist`, `messagingWhitelist`. The avatar image key is `icon`, not `avatar`.

Canvas editing stays on `system/canvas-agent`. Hand that work off through `system/agents` instead of enabling canvas skills on the package you are writing.

### Tool calls and MCP

You choose abilities. Fontana turns those into tool calls. Do not write a `tools` list in frontmatter.

A call id is either a built-in name (`email_send`) or an MCP name `mcp_<connection-slug>_<tool-name>`. Example: connection `knowledge-graph` and tool `kg_search` is `mcp_knowledge-graph_kg_search`. A trailing `.*` loads every tool that connection has discovered.

#### Calls every chat agent already has

These are present on every chat agent. Do not add them under `skills`.

| Call | What it does |
| --- | --- |
| `system_renderUrl` | Show a link the person can open. It does not change the page until they click Open, and it does not browse the page. |
| `system_updateThreadTitle` | Set the chat thread title. |
| `system_createTaskTree` | Start a task list for this turn. |
| `system_addSubtasksUnderActiveTask` | Add subtasks under the task that is active now. |
| `system_addSubtasksUnderParent` | Add subtasks under a named open task. |
| `system_closeTask` | Close one task. Closing a parent cancels unfinished child tasks. |
| `system_compactThreadContext` | Fold older thread history into a summary. |
| `system_evictContext` | Drop stale tool results from later turns. A stub remains so the agent can fetch them again. |
| `system_wait` | Pause, then continue, when a page, a browser session, or other work is not ready yet. |
| `icon_generateIcon` | Draw a minimal SVG icon from a text prompt. The package image is still a file under `avatars/`, not this call. |
| `skills_listSkillsCatalog` | List skills this agent may activate. |
| `skills_activateSkill` | Turn a skill on for this turn. |
| `skills_closeSkill` | Turn that skill off. |
| `skills_readSkillFile` | Read a file inside an active skill. |
| `hitl_askHuman` | Ask the person a structured question in chat. The answer comes back as an action plus values. |
| `agents_createSubAgentThread` | Open a side thread with an agent on the `system/agents` allow-list. |
| `agents_continueSubAgentThread` | Continue that side thread. |
| `agents_handoffThread` | Hand this thread to an agent on that allow-list. |
| `agents_delegateExternalAgent` | Ask a peer agent connected through Agent Interop. |

Delegation needs `system/agents` with the target ids in `agents`. The four `agents_*` thread calls above are still always present; the allow-list decides who they may reach.

#### Calls an ability adds

Enable only the rows the job needs.

**`system/knowledge-graph`** (MCP connection `knowledge-graph`). Search stays inside `namespaces`. The four `knowledge_` calls write the graph. Use them only when the operator asked for extraction or curation.

| Call | What it does |
| --- | --- |
| `mcp_knowledge-graph_kg_search` | Hybrid search. Returns capped chunk packages (text, citation, section, mentions). |
| `mcp_knowledge-graph_kg_open` | Open packages by one of `chunkKey`, `outlineKey`, `entityKey`, or `fileId`. |
| `mcp_knowledge-graph_kg_hop` | Step to a neighbour: next or previous chunk, similar files, mentions, relations, same type, or outline child, parent, or siblings. |
| `mcp_knowledge-graph_kg_outline` | A file's section index. |
| `mcp_knowledge-graph_kg_ontology` | Published entity types and relation types for one namespace. |
| `mcp_knowledge-graph_kg_entity_search` | Find an entity by name. |
| `mcp_knowledge-graph_kg_file_entities` | Entities mentioned in one file. |
| `mcp_knowledge-graph_kg_file_triples` | Typed relations whose subject and object are both mentioned in one file. |
| `mcp_knowledge-graph_kg_namespaces` | Namespaces this caller may search. |
| `mcp_knowledge-graph_kg_collections` | Collections in a namespace, and the folders that belong to them. |
| `mcp_knowledge-graph_kg_files` | Find files by folder prefix, path glob, or content regex. |
| `mcp_knowledge-graph_kg_file` | Read one file: metadata, a text window, SQL on csv or tsv, or a JSON query. |
| `mcp_knowledge-graph_kg_cypher` | One read-only OpenCypher statement for an exact word, a figure, or a known path. At most 50 rows. A citation is the file path plus the chunk text. |
| `knowledge_upsertKgInstanceTriples` | Write instance triples. |
| `knowledge_setKgEntityTypeMembership` | Set an entity's type. |
| `knowledge_applyKgOntologyProposals` | Apply proposed ontology changes. |
| `knowledge_mergeKgEntities` | Merge two entities. A later merge does not undo it. |

**`system/files`** reads and writes workspace files, including the Fontana Files store (MCP connection `ffs`).

| Call | What it does |
| --- | --- |
| `vfs_grep` | Find a workspace file by its contents. |
| `vfs_file_info` | Size and type. Use this before reading a file you have not seen. |
| `vfs_read` | Read a text range. A binary file returns metadata, not bytes. |
| `vfs_update` | Write a new version of a text file. Read it in the same turn first. |
| `mcp_ffs_ffs_list_collections` | List Fontana Files collections the caller can read. |
| `mcp_ffs_ffs_create_collection` | Create a collection. |
| `mcp_ffs_ffs_delete_collection` | Delete a collection. |
| `mcp_ffs_ffs_read_file` | Read a UTF-8 file. The path is relative to the collection root. |
| `mcp_ffs_ffs_write_file` | Write or replace a file in a collection. |
| `mcp_ffs_ffs_list_files` | List files and folders under a path. |
| `mcp_ffs_ffs_delete_file` | Delete a file or an empty folder. |
| `mcp_ffs_ffs_history_log` | History for a path or a whole collection. |
| `mcp_ffs_ffs_history_show` | Show one commit. |
| `mcp_ffs_ffs_history_revert_path` | Restore a path to an earlier commit. |
| `mcp_ffs_ffs_history_revert_collection` | Restore a whole collection to an earlier commit. |

**`system/data`** reads workflow run rows. Every call needs the workflow id from the operator, never a placeholder.

| Call | What it does |
| --- | --- |
| `data_listResources` | List what a run produced. |
| `data_queryData` | Query those rows. Keep the query narrow. |
| `data_queryWorkflow` | Read one part of the workflow configuration. |

**`system/workflows`** is the Projects surface.

| Call | What it does |
| --- | --- |
| `workflow_listUserWorkflows` | Resolve a workflow the person owns to a real id. |
| `workflow_searchWorkflows` | Find template workflows by meaning. `autoSearchWorkflows` runs this on a new prompt. |
| `workflow_startWorkflowRun` | Start a run when the operator asked for one. |

**`system/workflow-documents`** edits the markdown tabs on a workflow, not the canvas and not the Knowledge Graph.

| Call | What it does |
| --- | --- |
| `workflow_createWorkflowDocument` | Create a document tab. |
| `workflow_readWorkflowDocument` | Read one tab. |
| `workflow_updateWorkflowDocumentContent` | Replace or patch the markdown. |
| `workflow_renameWorkflowDocument` | Rename a tab. |
| `workflow_deleteWorkflowDocument` | Delete a tab. |

**`system/agents`** adds package and schedule admin on top of the delegation calls above. `agents` is who this agent may delegate to.

| Call | What it does |
| --- | --- |
| `agents_listAgents` | Resolve a display name to an agent id. |
| `agents_listAgentNamespaces` | List agent namespaces. |
| `agents_manageAgentNamespace` | Create or update a namespace. |
| `agents_reconcileAgentNamespace` | Re-register the packages in a namespace. |
| `agents_listAgentFiles` | List files in an agent package. |
| `agents_readAgentFileContent` | Read `AGENT.md` or another package file. |
| `agents_upsertAgentFileText` | Write a package file. Saving `AGENT.md` registers the agent. |
| `agents_deleteAgentFile` | Delete a package file. |
| `agents_moveAgentFile` | Move a package file. |
| `agents_manageAgentFolder` | Create or remove a folder in the agent tree. |
| `agents_generateAgentFileUploadUrl` | Prepare an upload for a binary package file. |
| `agents_registerAgentUploadedFile` | Register that upload. |
| `agents_listAgentSchedules` | List schedules defined on a package. |
| `agents_listMyAgentScheduleActivations` | List schedules this person has turned on. |
| `agents_activateAgentSchedule` | Turn a shared schedule on for this person. |
| `agents_disableAgentSchedule` | Turn that activation off. |
| `agents_upsertAgentEventSchedule` | Create or update an event schedule. |
| `agents_triggerAgentSchedule` | Run a schedule now. |

**`system/email`** is this agent's mailbox. Receive tools obey `receiveWhitelist`. `email_send` obeys `sendWhitelist`. An empty send list sends to nobody.

| Call | What it does |
| --- | --- |
| `email_listInbox` | List messages in the mailbox. |
| `email_search` | Search the mailbox. |
| `email_read` | Read one message, including its attachment list. |
| `email_draft` | Save a draft for a person to review. |
| `email_send` | Send. Every recipient must match the send whitelist. |

**`system/messaging`** is Slack (MCP connection `slack-channels`). Posts stay inside `messagingWhitelist`. `hitl_slackBlocks` is the Approve / Reject path. A plain post cannot carry that callback.

| Call | What it does |
| --- | --- |
| `mcp_slack-channels_list_installations` | List Slack installations. Other Slack calls need an installation id. |
| `mcp_slack-channels_list_conversations` | List channels and conversations the bot can see. |
| `mcp_slack-channels_get_conversation_history` | Read recent messages. The bot must already be in the channel. |
| `mcp_slack-channels_post_message` | Post or reply as the Fontana bot. |
| `mcp_slack-channels_list_users` | List people in the workspace. |
| `mcp_slack-channels_get_user` | Read one Slack profile. |
| `hitl_slackBlocks` | Ask for an Approve / Reject decision in Slack. |
| `voice_generateSpeech` | Speak a short answer aloud. |

**`system/teams`** is this agent's own Teams bot (MCP connection `teams-channels`). Turning the ability on creates the bot.

| Call | What it does |
| --- | --- |
| `mcp_teams-channels_list_installations` | List this tenant's Teams bots. |
| `mcp_teams-channels_post_message` | Post into a channel as this agent's bot. The app must already be installed in that team. |

**`system/coding`** is the OpenSandbox connection `session`. `mcp_session_open`, `mcp_session_exec`, and `mcp_session_close` run code in an isolated sandbox. The sandbox does not see Fontana data unless the agent passes that data in, and files written there do not persist. Leave `toolSubset` empty to load every tool that connection has discovered.

**`system/fontana-browser`** browses live pages. The same tools exist on connections `fontana-browser` and `steel`. Prefer the `mcp_fontana-browser_` ids. Leave `toolSubset` empty unless the operator named a subset. `steel_scrape`, `steel_screenshot`, and `steel_pdf` do not start a browser session. The session tools do.

| Call | What it does |
| --- | --- |
| `mcp_fontana-browser_steel_scrape` | Read a page as markdown or HTML. |
| `mcp_fontana-browser_steel_screenshot` | Capture a screenshot of a page. |
| `mcp_fontana-browser_steel_pdf` | Render a page to PDF. |
| `mcp_fontana-browser_steel_session_options` | Plan a session before creating one. |
| `mcp_fontana-browser_steel_session_create` | Start a browser session. |
| `mcp_fontana-browser_steel_navigate` | Open a URL in that session. |
| `mcp_fontana-browser_steel_snapshot` | Read the current page as a tree of elements the next call can act on. |
| `mcp_fontana-browser_steel_find` | Find one element on the current page. |
| `mcp_fontana-browser_steel_act` | Click, type, select, scroll, or press a key. |
| `mcp_fontana-browser_steel_wait_for` | Wait until text, a selector, or a URL is present. |
| `mcp_fontana-browser_steel_batch` | Run several reversible steps in one call. |
| `mcp_fontana-browser_steel_session_diagnostics` | Read activity from a live or finished session. |
| `mcp_fontana-browser_steel_session_handoff` | Let the person drive the live session, then resume. |
| `mcp_fontana-browser_steel_session_replay` | Return a replay link for a finished session. |
| `mcp_fontana-browser_steel_session_live_view` | Connection details for the on-screen preview. The model does not receive page content from this call. |
| `mcp_fontana-browser_steel_session_release` | End the session. |

**`system/agent-memory`** stores durable notes for this agent in the Knowledge Graph `memory` namespace.

| Call | What it does |
| --- | --- |
| `knowledge_addMemory` | Remember a preference, decision, or correction. |
| `knowledge_forgetMemory` | Remove a memory the person retracted. |

**`system/system-one`** asks TypeSafe System One for one calibrated decision.

| Call | What it does |
| --- | --- |
| `systemone_ask` | Ask one typed question. Returns a decision and a confidence. Report both as returned. |

#### MCP the operator already connected

Seeded connections are the abilities above. Do not also add `system/mcp-<slug>` for these slugs: `knowledge-graph`, `ffs`, `slack-channels`, `teams-channels`, `session`, `steel`, `fontana-browser`.

Any other connection the operator created on **AI → Tools** is `system/mcp-<slug>`, where `<slug>` is that connection's slug. `{}` loads every tool the connection has discovered, as `mcp_<slug>_<tool-name>`. `toolSubset` is a list of those ids when the operator wants fewer.

Use the slug and the tool names the operator gave you. Do not invent either. If they did not name a connection, leave `system/mcp-*` off the package.

`toolSubset` on Slack, Coding, and Fontana Browser is a list of `mcp_<connection>_<tool>` ids. Omit it to load the whole connection. Teams has no `toolSubset`.

Page abilities (`system/dashboard-pages`, `system/skills-admin`, `system/mcp-admin`, and the other `*-pages` packages) belong to Fontana agent. Leave them off the package you are writing. `system/mcp-admin` is how Fontana agent registers a connection. It is not how you attach one.

### Permissions

`permissions: ["*"]` allows every catalog permission. At runtime the usable set is the invoking person's role overlapped with this list. Narrower entries are ids such as `knowledge-graph:read` or a resource wildcard such as `workflows.*`.

### Call settings

A mapping, or `{}`. Runtime reads these keys only: `temperature`, `maxOutputTokens`, `topP`, `topK`, `presencePenalty`, `frequencyPenalty`, `stopSequences`, `seed`. Use `temperature: 0` for analytical work unless the operator asked otherwise.

### System prompt body

Write a specialist brief, in Markdown, after the frontmatter:

1. **Role:** expertise, tone, and the hard limits a legal, medical, or financial domain needs
2. **Context:** who it serves, typical assignments, when to escalate
3. **Core responsibilities:** verb-led
4. **Operating principles:** how it separates fact, interpretation, and recommendation
5. **Workflow:** intake, analysis, delivery, self-check
6. **Output format:** the markdown skeleton to return
7. **Quality bar:** checks before it finishes
8. **Handoff:** when to hand Fontana product questions to `system/fontana-agent`

Keep platform mechanics out of the body (thread compaction, knowledge-graph injection, delegate tables). The runtime adds those when the abilities are enabled.

`description` and `vectorSource` stay about the domain, not about Fontana Agent itself.

## schedules.json

Optional. When you include it, the document has one key, `schedules`, and each entry has `id`, `name`, `prompt`, and `schedule`. Ids are unique inside the file.

Cron uses `expr` (UTC), never a field named `cron`:

```json
{
  "schedules": [
    {
      "id": "daily-digest",
      "name": "Daily digest",
      "prompt": "Summarise overnight activity.",
      "schedule": { "kind": "cron", "expr": "0 8 * * *" }
    }
  ]
}
```

Workflow events set `kind` to `"event"`, `event` to one of `workflow_run_completed`, `workflow_run_failed`, `workflow_run_succeeded`, `exception_raised`, `exception_status_changed`, and `workflowId` to the operator's workflow id. `email_received` omits `workflowId`. `{ "kind": "manual" }` never runs on a timer.

Omit `schedules.json` when the operator did not ask for a schedule. They can add one later in the Agents editor.

## Example package

`nav-analyst/AGENT.md`:

```md
---
title: NAV Analyst
role: NAV analyst
description: Reviews NAV packs and explains breaks in plain language for the fund accounting team.
vectorSource: NAV analyst net asset value breaks reconciliation
model: ""
scopes:
  - chat
skills:
  system/knowledge-graph: {}
  system/agents:
    agents:
      - system/fontana-agent
isActive: true
permissions:
  - "*"
reasoningEffort: high
callSettings:
  temperature: 0
---

## Role

You are a NAV analyst for the fund accounting team. You explain breaks in plain language. Sign-off and investment advice stay with the team.

## Context

You serve accountants who upload a pack or name a fund and a date. When the request is about Fontana itself (where to click, how agents work), hand off to `system/fontana-agent`.

## Core responsibilities

- Restate the fund, date, and question before you analyse.
- Separate figures you were given from calculations you made.
- Name the source section for every figure you cite.

## Workflow

1. Confirm fund, date, and the question.
2. Use enabled Knowledge Graph namespaces when the pack is already filed there.
3. Deliver the skeleton below.
4. Check that every number traces to a source you were given.

## Output format

- **Question**
- **Findings**
- **Sources**
- **Open items**

## Handoff

Hand Fontana product and navigation questions to `system/fontana-agent`.
```

## Before you finish

Confirm all of the following, then tell the operator the folder name, the `title`, and the upload path.

- The directory contains `AGENT.md` directly inside it.
- Frontmatter has `title`, `description`, and `vectorSource`, and the body is a real system prompt.
- Frontmatter omits `id`, `name`, and `avatar`.
- `skills` keys are catalog ids. Settings match the table above.
- `scopes`, when present, lists only the values in this skill.
- `icon`, when present, is `avatars/<filename>` and that file is in the folder.
- `schedules.json`, when present, is one JSON object with a `schedules` array, and cron triggers use `expr`.

## Upload

1. Open **AI → Agent packages** (`/ai/agents`).
2. Select a namespace the operator created.
3. Choose **Upload folder** and select the package directory.
4. Open the imported package and confirm the title, abilities, and prompt.
