Project files
A Maitento project is a folder of small text files. Each kind of definition has its own folder, and the file name
is the definition’s name. This reference lists every kind of file and every property it can set. It is generated
from Maitento’s code, so it matches what a deploy accepts. The same description is published as
sdks/mtr-schema.json for tools, and drives the
VS Code extension.
The folder
Section titled “The folder”<project>/├── agents/ agents (.mtr)├── interactions/│ ├── one-shot/ one-shot interactions (.mtr)│ ├── round-robin/ round-robin interactions (.mtr)│ └── managed/ managed interactions (.mtr)├── connectors/│ └── open-api/ connectors (.mtr)├── external-operations/│ └── open-api/ tools (.mtr)├── capsules/ capsules (.mtr)├── looms/ looms (.mtr)├── apps/│ └── <name>/ app settings (.mtr, optional); app code (*.mtc)├── prompts/ prompt files (*.md)├── json/ JSON files (*.json)├── code-pipelines/│ └── <name>/ pipeline-definition.json└── code-pipeline-hooks/ └── <name>/ code pipeline hooks (*.mtc)Sub-folders inside a kind’s folder are fine. Anything else in the project, such as a README, is ignored.
| Folder | What a file there defines | Reference |
|---|---|---|
agents/ | An agent: a model with standing instructions, a one-line summary and the tools it may use. | Agents |
interactions/one-shot/ | A one-shot interaction: one agent, one task, one answer. | One-shot interactions |
interactions/round-robin/ | A round-robin interaction: agents, and optionally a person, take turns in one shared conversation. | Round-robin interactions |
interactions/managed/ | A managed interaction: a manager agent owns the task and hands pieces of work to named team members, who see only what the manager sends them. | Managed interactions |
connectors/open-api/ | A connector: one HTTP endpoint, described once. | Connectors |
external-operations/open-api/ | A tool: what an agent sees and calls. | Tools |
capsules/ | A capsule: the recipe for a short-lived Linux sandbox. | Capsules |
looms/ | A named loom: a long-term memory several interactions can share. | Looms |
apps/<name>/ | An app’s settings: the optional .mtr file beside an app’s Cogniscript (.mtc) code. | App settings |
Tools are known in Maitento as external operations (extops), which is why their folder is
external-operations/open-api/.
A small project
Section titled “A small project”The 02-prompts-and-inputs example: an agent, an interaction that puts it to work, and the two prompt files they include.
model = @ref("deepseek.deepseek-v4-flash")prompt = @prompt("poet")summary = "A poet who writes short poems"agent = { name = "Poet" agent = @ref("poet")}task = @prompt("haiku-task")inputs.prompts = [ { name = "topic" description = "What the haiku is about" required = true }, { name = "mood" description = "Optional mood, for example calm or playful" required = false }]Write a haiku about %%topic%%.{{#if mood}}The mood of the haiku should be %%mood%%.{{/if}}You are a poet who writes short, vivid poems.You only ever reply with the poem itself: no title, no explanation.Writing .mtr files
Section titled “Writing .mtr files”One name = value per line. Comments start with //.
Values
Section titled “Values”| Written | Example | Meaning |
|---|---|---|
"text" | "You are a friendly assistant." | Text in double quotes, taken exactly as written: \n stays a backslash and an n, and the text may run over several lines. Put anything long in a prompt file and use @prompt("name"). |
123 or 0.5 | 0.85 | A number, without quotes. |
true or false | true | true or false, without quotes. |
{ name = value ... } | agent = { name = "Greeter" agent = @ref("greeter") } | A block of properties in braces, one name = value after another, with no commas. |
[ value, value ] | packages = ["git", "curl"] | A list in square brackets with commas between the items. A list cannot be empty: leave the property out instead. |
References
Section titled “References”A property that names another definition takes a reference. Each property’s entry says what it must name.
| Form | Means |
|---|---|
@ref("name") | Another definition, by name, in the namespace you deploy to. It may be declared in the same project, or already exist. |
@ref("name", "namespace") | A definition in another namespace. |
@ref(id) | A definition by its id, without quotes. |
Including a file
Section titled “Including a file”| Form | Reads | Means |
|---|---|---|
@prompt("name") | prompts/<name>.md | The text of a prompt file, as the value of a text property. It cannot be an item of a list. |
@json("name") | json/<name>.json | The text of a JSON file, as the value of a text property, usually a JSON Schema. It cannot be an item of a list. |
A map property takes one line per entry: the property’s name, a colon and the key, then the value as text.
bindings.query:units = "metric"Inputs in text
Section titled “Inputs in text”In an interaction’s task, and in the prompt files it includes, %%name%% is replaced by the run’s input name. {{#if name}}...{{/if}} keeps its text only when the input has a value, and {{#unless name}}...{{/unless}} only when it has none. Every block must be closed.
Rules that catch people out
Section titled “Rules that catch people out”-
Put spaces around
=. Without them, the name, the=and the value read as one word.Wrong:
summary="A friendly assistant"
Right:summary = "A friendly assistant" -
A name with dots is one name.
inputs.promptsis written as it is, never as a block namedinputs.Wrong:
inputs = { prompts = [ { name = "topic" } ] }
Right:inputs.prompts = [ { name = "topic" } ] -
A block holds
name = valueentries with no commas between them. Lists have commas.Wrong:
agent = { name = "Greeter", agent = @ref("greeter") }
Right:agent = { name = "Greeter" agent = @ref("greeter") } -
A list cannot be empty. Leave the property out instead.
Wrong:
functions = []
Right:// no functions -
Numbers and
true/falsehave no quotes, and text always has them.Wrong:
allowWebSearch = "true"
Right:allowWebSearch = true -
Set each property once in a file, and once in each block.
Wrong:
summary = "A" summary = "B"
Right:summary = "B" -
@promptand@jsongive the value of a text property. They cannot be items of a list.Wrong:
prompts.system = [ @prompt("house-style") ]
Right:prompts.system = [ "Write in British English." ] -
A file needs at least one property or comment: an empty file does not build.
Right:
// Settings for this app: none yet.
A resource’s name is its file name without .mtr (an app’s is its folder’s name). Use letters, digits, _, - and . (but not ..), at most 128 characters. Two files of the same kind may not have the same name, even in different sub-folders or with different capitals.
Other files
Section titled “Other files”Prompt file
Section titled “Prompt file”Text for any text property, included with @prompt("name"): prompts/name.md, in any sub-folder of prompts/. A file is found by its name alone, so keep names unique. The text may use the run’s inputs as %%name%%, and {{#if name}}...{{/if}} / {{#unless name}}...{{/unless}} blocks, which must be balanced.
JSON file
Section titled “JSON file”JSON, usually a JSON Schema, included with @json("name"): json/name.json, in any sub-folder of json/. A file is found by its name alone, so keep names unique.
App code
Section titled “App code”An app’s program, in Cogniscript: apps/<app>/*.mtc, at least one per app (an app folder without one is skipped). The program starts at main, and main’s parameters are the app’s inputs. An optional .mtr beside it holds the app’s settings.
Code pipeline definition
Section titled “Code pipeline definition”A code pipeline: code-pipelines/<pipeline>/pipeline-definition.json. Its name must be the folder’s name. A pipeline folder without the file is skipped.
| Include | Reads | Means |
|---|---|---|
"@prompt(name)" | code-pipelines/<pipeline>/prompts/<name>.md | Replaced by the text of the pipeline’s own prompt file, as a JSON string. A missing file fails the whole build. |
"@schema(name)" | code-pipelines/<pipeline>/<name>.schema.json | Replaced by the text of the pipeline’s schema file, as a JSON string. A missing file fails the whole build. |
"@externalOp(namespace/name)" | <namespace>/<tool> | Replaced by the id of a tool, which may be declared in the same project. |
Code pipeline hook
Section titled “Code pipeline hook”Cogniscript functions a code pipeline runs between its phases: code-pipeline-hooks/<pipeline>/*.mtc. Every top-level function is string Name(string processId, string methodName).
| Include | Reads | Means |
|---|---|---|
@promptJson(pipeline/name) | code-pipelines/<pipeline>/prompts/<name>.md | Inside a string literal: replaced by the prompt file’s text, escaped for a JSON string. |
@schemaJson(pipeline/name) | code-pipelines/<pipeline>/<name>.schema.json | Inside a string literal: replaced by the schema file’s text, escaped for a JSON string. |
The files, kind by kind
Section titled “The files, kind by kind”- Agent files: An agent: a model with standing instructions, a one-line summary and the tools it may use.
- One-shot interaction files: A one-shot interaction: one agent, one task, one answer.
- Round-robin interaction files: A round-robin interaction: agents, and optionally a person, take turns in one shared conversation.
- Managed interaction files: A managed interaction: a manager agent owns the task and hands pieces of work to named team members, who see only what the manager sends them.
- Connector files: A connector: one HTTP endpoint, described once.
- Tool files: A tool: what an agent sees and calls.
- Capsule files: A capsule: the recipe for a short-lived Linux sandbox.
- Loom files: A named loom: a long-term memory several interactions can share.
- App settings files: An app’s settings: the optional
.mtrfile beside an app’s Cogniscript (.mtc) code.