Skip to main content

Package manifest (apollia.toml)

A package is a folder with an apollia.toml at its root. The manifest declares what the package delivers: agents, which are data, Python tools, Python workflows, the connections it needs, the MCP servers it brings, its Python dependencies and the triggers it proposes. apollia-os package build turns the folder into a .apo archive, and reading the manifest never runs the code of the package.

This file shares its name with the configuration file of the runtime, described in Configuration (apollia.toml). They are two different files: this one sits at the root of a package folder and travels inside the archive.

Strict schema​

The schema is strict. A key the schema does not know is refused, and the refusal names the full path of the key:

apollia.toml: unknown key `agents[0].defaults.model.temprature`

Nothing is ignored, so what you write is exactly what Apollia reads.

Tables​

TableCardinalityDeclares
[package]one, requiredThe identity of the package.
[[agents]]zero or moreAgents: a mission, examples and defaults. No code.
[[tools]]zero or morePython tools, each reachable as pkg:<package>/<name>.
[[workflows]]zero or morePython workflows with their declared steps.
[[requires]]zero or moreConnections the package needs.
[[mcp_servers]]zero or moreMCP servers the package brings.
[pip]zero or onePython dependencies of the package environment.
[[triggers]]zero or moreTriggers the package proposes.

A package declares at least one agent, one tool or one workflow.

[package]​

KeyTypeRequiredMeaning
namestringyesIdentifier of the package, [a-z0-9_-]+. Prefix of its tools: pkg:<name>/<tool>.
versionstringyesSemver version of the package, for example 1.2.0.
publisherstringyesPublisher shown when the package is installed.
descriptionstringnoWhat the package delivers.
sdkstringyesSemver requirement on the SDK the package was written against, for example ">=0.3, <0.4".

[[agents]]​

An agent is data. The built-in agent engine runs it; the package ships no code for it.

KeyTypeRequiredMeaning
idstringyesIdentifier, [a-z0-9_-]+, unique in the package.
namestringyesDisplay name.
missionstringyesWhat the agent is for, in the words of its author. Used as its instructions.
exampleslist of stringsnoExample requests shown on the sheet of the agent.

[agents.defaults]​

Every value here is a default the package recommends, never a constraint: an override the user sets on their machine takes precedence, and a package update keeps it.

KeyTypeMeaning
accesslist of stringsTools granted by default: a native tool name, mcp:<server>/<tool>, or pkg:<package>/<tool>. A pkg: entry must name a tool of this package. agent:<id> and workflow:<package>/<workflow> let the agent call another agent or a workflow, each offered to it as one more tool. Nothing the list does not name is offered to the agent.
sourceslist of stringsSources checked by default. "profile" lets the agent read the user profile through ctx.profile; "memory" opens its memory, to read and to write. Any other entry is a source identifier, as apollia-os source list shows it.
autonomystringAutonomy tier: assisted, supervised, bounded_autonomous or long_autonomous. Without it, the global default applies.
planningstringWhether the agent plans a task before acting on it: never, auto or always. Without it, auto.

[agents.defaults.model]​

KeyTypeMeaning
modelstringModel the package recommends.
presetstringPreset of request settings the package recommends.

[agents.defaults.model.request] carries the request settings themselves: temperature, top_p, top_k, repetition_penalty, max_tokens and seed.

[[tools]]​

One entry per Python tool. python -m apollia describe <folder> writes these entries from the functions decorated with @tool, so that the manifest and the code cannot disagree.

KeyTypeRequiredMeaning
namestringyesIdentifier, [a-z0-9_-]+, unique in the package.
modulestringyesPython module, relative to the package root, for example tools/invoices.py.
descriptionstringyesWhat the tool does, for the model and for the sheet of the agent.
actionstringyesAction family, see below.
inputstablenoJSON Schema of the inputs.

Action families​

A tool and a workflow each declare one action family: what calling it does to the world. Every family except read makes the access sensitive.

FamilyMeaningSensitive
readReads data that is not personal.no
read_personalReads personal data: mail, calendar, the documents of a user.yes
write_or_deleteWrites or deletes.yes
send_externalSends something outside the machine.yes
execute_codeExecutes code.yes

[[workflows]]​

One entry per Python workflow, written by python -m apollia describe <folder> from the functions decorated with @workflow.

KeyTypeRequiredMeaning
namestringyesIdentifier, [a-z0-9_-]+, unique in the package. The workflow is addressed as <package>/<name>.
modulestringyesPython module, relative to the package root.
descriptionstringyesWhat the workflow does.
actionstringyesAction family: the most sensitive thing the workflow does.
inputstablenoJSON Schema of the inputs. Its x-order key lists them in the order the launch form follows.
stepslist of stringsnoNames of the steps, in order.

[[requires]]​

KeyTypeRequiredMeaning
typestringyesConnection type, as the connection catalogue names it, for example gmail.
reasonstringnoWhy the package needs it, shown when the connection is missing.

[[mcp_servers]]​

The keys, defaults and meaning are those of a server in mcp.toml.

KeyTypeDefaultMeaning
namestringrequiredServer name, [a-z0-9_-]+. Prefix of its tools: mcp:<name>/<tool>.
commandstringemptyExecutable to spawn; empty for a network transport.
argslist of stringsemptyArguments handed to the command.
envtableemptyEnvironment of the server process; ${VAR} placeholders are allowed.
transportstringstdiostdio, streamable-http or sse.
urlstringnoneServer URL for a network transport.
init_timeout_secsinteger30Timeout of the initialize handshake.
call_timeout_secsinteger60Timeout of one tools/call.
max_response_bytesinteger8388608Cap on one server response.
max_toolsinteger256Cap on the tools kept from tools/list.
tagslist of stringsemptyTags applied to every tool of the server.

A server carries no approval setting. requires_approval, a key of earlier versions, is still read, logs a package.manifest.retired_key warning and does nothing: whether a call to one of its tools asks first is decided on the action family of that tool.

[pip]​

KeyTypeMeaning
packageslist of stringsRequirements installed in the environment of the package. Pin them (pypdf==4.3.1).

[[triggers]]​

A package proposes triggers; installing it does not arm them on its own.

KeyTypeRequiredMeaning
idstringyesIdentifier, [a-z0-9_-]+, unique among the triggers.
targetstringyesThe agent or the workflow of this package that the trigger starts.
inputstringnoMessage sent to an agent each time the trigger fires.
sourcetableyesWhen it fires, see below.

[triggers.source] is tagged by type:

typeKeysFires
cronscheduleOn a cron expression, for example "0 8 * * MON".
intervaleveryAt a fixed interval: "30m", "1h", "1d".
file_watchrecursive (default false)When a folder changes. The user picks the folder at install time.
webhooknoneOn an HTTP call. The secret is set at install time, never in the manifest.

Validation​

Beyond the schema, a manifest holds these rules. The first one broken is reported, and the package is neither built nor installed.

RuleMessage
The package declares at least one agent, workflow or tool.the package declares no agent, no workflow and no tool
The package name, every identifier and every MCP server name match [a-z0-9_-]+.`<field>` value `<value>` must match [a-z0-9_-]+, or MCP server name `<name>` must match [a-z0-9_-]+ for an MCP server
version is semver.package version `<value>` is not semver
sdk is a semver requirement.sdk requirement `<value>` is not a semver requirement
Agents, tools and workflows share one namespace with no duplicate. Trigger identifiers are unique, and so are MCP server names.identifier `<id>` is declared more than once
A default access pkg:<package>/<tool> names a tool of this package.agent `<agent>` grants `<access>`, which is not a tool of package `<package>`
A trigger targets an agent or a workflow of this package.trigger `<trigger>` targets `<target>`, which is no agent or workflow of the package

apollia-os package build adds one check of its own: it refuses a folder whose Python modules define tools or workflows that the manifest does not describe.

Complete example​

[package]
name = "invoices"
version = "1.2.0"
publisher = "Example Accounting"
description = "Reads supplier invoices and drafts the reminders."
sdk = ">=0.3, <0.4"

[[agents]]
id = "invoice-clerk"
name = "Invoice clerk"
mission = "Read the supplier invoices of the month and list the late ones."
examples = ["Which invoices are late?", "Draft a reminder for ACME."]

[agents.defaults]
access = ["file_read", "mcp:ledger/lookup", "pkg:invoices/extract_totals"]
sources = ["profile"]
autonomy = "supervised"
planning = "always"

[agents.defaults.model]
model = "qwen3-8b-instruct"
preset = "balanced"

[agents.defaults.model.request]
temperature = 0.2
max_tokens = 2048

[[tools]]
name = "extract_totals"
module = "tools/extract.py"
description = "Extract the total, the due date and the supplier of an invoice."
action = "read_personal"

[tools.inputs]
type = "object"
required = ["path"]

[tools.inputs.properties.path]
type = "string"
description = "Path of the invoice file."

[[workflows]]
name = "monthly-reminders"
module = "workflows/reminders.py"
description = "Find the late invoices and send one reminder per supplier."
action = "send_external"
steps = ["collect", "confirm", "send"]

[workflows.inputs]
type = "object"

[workflows.inputs.properties.month]
type = "string"

[[requires]]
type = "gmail"
reason = "Reminders are sent from the user's mailbox."

[[mcp_servers]]
name = "ledger"
command = "uvx"
args = ["ledger-mcp"]

[pip]
packages = ["pypdf==4.3.1"]

[[triggers]]
id = "first-monday"
target = "monthly-reminders"

[triggers.source]
type = "cron"
schedule = "0 8 1-7 * MON"