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

# Process Agents

> Every routine of the orchestrator as a configurable agent: its skills, its triggers (schedule, event, deadline, manual), its autonomy, its runs

The orchestrator used to hard-wire its routines: PARTIN answers, then
APERAK, then the Zuordnungsermächtigungen, then the mailbox, the day
steps, the reBAP reads, the confirmations, the contract check, the cases,
the Slack log - each switched by a settings flag, each with its own
interval buried in its code. They are **process agents** now: a
definition in a ledger on the audit share, with the skills it carries,
the triggers that wake it, its autonomy and its place in the order. This
is PR 2 of the [agentic process support
design](/setup/agentic-process-support.md); it changes no behaviour, it makes
the behaviour configurable.

> [!NOTE]
>
> The hash-driven day steps (aggregate, publish, submit) and the watchdogs
> (gate closure, trader deadline) stay in the orchestrator itself - design
> rule D11: the pipeline is never an agent. `orchestrate()` is now: the
> heartbeat, the agents before the day steps, the day steps, the watchdogs,
> the agents after the day steps.

## The built-in agents

One per routine, in the old order. `order` below 100 runs before the day
steps, above 100 after them.

| Agent | Skill | Order | Gate (as before) | Switched by |
| - | - | - | - | - |
| `forecast-generation` | the horizon's forecasts from mirrored data | 10 | - | `AUTO_GENERATE_FORECAST` |
| `backup-csv` | a backup series for every horizon day without a forecast | 20 | - | `AUTO_BACKUP_CSV` |
| `partin-answers` | answer incoming PARTINs | 30 | MakoFlow configured | `AUTO_ANSWER_PARTIN` |
| `aperak` | acknowledge every received message | 40 | MakoFlow configured | `AUTO_APERAK` |
| `auto-zoe` | grant and extend Zuordnungsermächtigungen | 50 | MakoFlow configured | `AUTO_ZOE` |
| `mailbox` | reconcile the mailbox, file handled mail | 60 | mailbox configured | `AUTO_MAILBOX` |
| `rebap-quality` | the quality-assured reBAP points, every 6 hours | 110 | netztransparenz configured, due | - |
| `rebap-operational` | the operational points, hourly | 111 | netztransparenz configured, due | - |
| `bestaetigungen` | the TSOs' confirmations, every 30 minutes | 120 | due | - |
| `vertragspruefung` | the contracts against what is, hourly | 130 | due | - |
| `cases-sync` | the state-driven [cases](/setup/cases.md) | 140 | - | - |
| `slack-protokoll` | the Slack interaction log | 150 | webhook configured | - |

Each is seeded with one schedule trigger, *every orchestrator run*
(`every_minutes: 0`), autonomy `act` (that is what the routines do today:
they send), and `enabled` from its flag. A skill's own interval and
configuration check - its **gate** - stays with the skill, so a 6-hourly
read is still 6-hourly whatever the trigger says; a gated skill that is
not due is *skipped* in the run log, not run. A skill's failure raises
the same event the routine raised before (`partin_answer_failed`,
`aperak_failed`, `zoe_auto_failed`, `mailbox_sync_failed`,
`fahrplan_bestaetigung_fehler`, `orchestration_error`,
`case_sync_failed`, `slack_protokoll_fehler`), so the alerting rules and
the operator app see what they saw.

**The flags.** Until they go (PR 6), a flag still switches its agent: a
flag moved in the console or the environment sets the agent's `enabled`
and records a new version saved by `settings`. An operator's own switch
in the agents tab holds until the flag moves again.

## Triggers

| Kind | Fields | Fires |
| - | - | - |
| `schedule` | `every_minutes` (0 = every orchestrator run), or `cron` with `timezone` | By interval, measured from the agent's last run; a cron slot that passed since the last run (or since the agent was saved - a new agent does not catch up on missed slots), looking back at most 24 hours |
| `event` | `type`, `where` (fields the event's `data` must carry) | The event log's subscriber queues a wake; the next orchestrator run carries it out. Several events before that run are one run |
| `deadline` | `clock` (`gate_closure`, `trader_deadline`), `lead_minutes` | Once per day, inside the window from `lead_minutes` before the clock's time (from the settings) to the time itself |
| `manual` | - | Only from the console or `POST /agents/{slug}/run` |

An agent with several triggers runs when any is due. A disabled agent is
neither woken nor scheduled.

## Runs

A run executes the agent's skills in order. Per skill: `ok` with a small
summary of the result, `skipped` with the reason (not configured, not
due, no preview in a dry run), or `failed` with the error - a failure
never stops the next skill. The last 50 runs per agent are kept
(`agent_runs.json`), the agent's state (last run, last trigger, counts)
in `agent_state.json`, pending wakes in `agent_wakes.json`.

A **dry run** (`behaviour.dry_run`, or `dry_run: true` on a manual run)
runs the skills that have a preview (PARTIN answers, APERAK, ZOE, the
mailbox, the cases, the Slack log) without writing, and skips the others.

## Definitions

| Field | Meaning |
| - | - |
| `slug`, `name`, `description`, `goal` | Purpose. The goal is handed to a model as standing context from PR 4 on |
| `skills` | From the registry (`GET /agents` lists it); an unknown skill is refused |
| `rules` | Markdown, one rule per line, numbered from P31 (PR 5 reads them) |
| `autonomy` | `propose`, `act_with_approval`, `act` (PR 3 enforces it per action) |
| `enabled`, `triggers`, `behaviour` (`dry_run`, caps, model), `order` | As above |
| `builtin`, `flag`, `version`, `saved_by`, `saved_at` | The service's: a built-in agent cannot be deleted, only disabled |

Every save is a new version with who and when; the version before goes
to `agents_history.json` (50 per agent). A run records the version it ran
on. The console tab **Agenten** lists every agent with its state and the
day-steps divider, runs one now (dry or real), switches it, and edits or
creates one with the form; the API does the same:

| Endpoint | Purpose |
| - | - |
| `GET /v1/process/agents` | Every agent with its state, the day-steps order, the skill registry |
| `POST /v1/process/agents` | A new agent from existing skills |
| `GET` / `PUT` / `DELETE /v1/process/agents/{slug}` | One agent; change (a new version); remove (not a built-in) |
| `POST /v1/process/agents/{slug}/run` | Run now, `{"dry_run": true}` to preview |
| `GET /v1/process/agents/{slug}/runs?limit=` | The last runs, newest first |

Events: `agent_saved` on every create, change or delete;
`agent_run_failed` (error) when a skill without a failure event of its
own raises, or the agents could not be read.


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