# Bestille en kjøring Dette dokumentet er for deg som **bestiller** en kjøring — fagpersonen som vet hvilke tilnærminger det er verdt å prøve på et prosjekt, og som vil vite nøyaktig hva systemet skal gjøre før det gjør det. Søsterdokumentet [ekspert-svar.md](ekspert-svar.md) handler om det motsatte enden: å avgi dommen etterpå. > **Ærlighetsmerking.** Bestillingen styrer hva som **vurderes**. Den styrer aldri hva som > **godkjennes**. Den deterministiske validatoren gjelder uendret for en tilnærming du selv har bedt > om — ber du om noe tallene ikke bærer, blir det avvist, og avvisningen kommer tilbake til deg med > begrunnelsen. ## Oppdragsfila En bestilling er én JSON-fil. Du gir den til kjøringen med `--mandate`. ```json { "objective": "Kutt energikostnad i BYGG-KONTOR-NORD uten ombygging, med tiltak som kan gjennomføres i 2026.", "approaches": [ { "id": "led-retrofit", "label": "LED-retrofit av kontorbelysning", "description": "Drift mener armaturene er originale og har gått langt forbi oppgitt levetid." }, { "id": "driftsavtale", "label": "Reforhandling av driftsavtale", "description": "Avtalen er ikke justert siden 2019 og dekker areal vi ikke lenger disponerer." } ], "allow_own_proposals": true, "success_criteria": "Minst ett tiltak som passerer validatoren og som drift kan stå inne for." } ``` | Felt | Hva det gjør | |---|---| | `objective` | Hva kjøringen er til for, i klartekst. **Påkrevd** — en kjøring uten uttalt hensikt er nettopp det denne fila finnes for å hindre. | | `approaches` | Tilnærmingene du vil ha vurdert. Hver får sin egen vurdering og sin egen linje i oppgjøret. | | `allow_own_proposals` | `true` (standard): systemet foreslår også sitt eget, i tillegg til dine. `false`: kun dine. | | `success_criteria` | Hva du vil regne som vellykket. Gjengis ordrett i kunngjøringen; ingenting tolker den maskinelt. | **Om `id`:** den er nøkkelen tilnærmingen rapporteres under. To tilnærminger kan ikke dele `id` (da ville de kollapset til én linje i oppgjøret), og `own-proposal` er reservert for systemets eget forslag. **Om `description`:** den mates ordrett inn til modellen. Det er her fagkunnskapen din faktisk gjør en forskjell — *hvorfor* du tror tilnærmingen er verdt å prøve er nøyaktig det systemet ikke kan lese seg til av kostnadstallene. **Enten tilnærminger eller egne forslag.** En fil med tom `approaches` **og** `allow_own_proposals: false` blir avvist: da har kjøringen ingenting å gjøre. ## Å kjøre den ```bash uv run python -m portfolio_optimiser.run BYGG-KONTOR-NORD \ --docs-dir shared/examples/bygg-energi-mikro \ --bundle-dir shared/examples/bygg-energi-mikro \ --mandate oppdrag.json \ --scripted-replies replies.json ``` `--mandate` virker i begge moduser. I porteføljemodus (`--portfolio`) gjelder bestillingen **hvert** prosjekt i passet, og hvert prosjekt gjør opp for seg. **Vil du se hva kjøringen ville gjort, uten å bruke penger?** Legg til `--live-dry-run`. Da skrives kunngjøringen, og kjøringen stopper før første modellkall. **Fila leses strengt.** Mangler den, eller er den feilformet, blir kjøringen **nektet** (rc 1) — den går aldri videre på en halvlest bestilling. Det er med vilje: et oppgjør som beskriver arbeid ingen har bestilt, er verre enn ingen bestilling. ## Hva du får: kunngjøringen Før noe koster penger, skriver kjøringen hva den skal gjøre: ``` Run mandate for BYGG-KONTOR-NORD Objective: Kutt energikostnad i BYGG-KONTOR-NORD uten ombygging, ... Evaluates: 2 expert-proposed approach(es) + the system's own proposals 1. led-retrofit — LED-retrofit av kontorbelysning 2. driftsavtale — Reforhandling av driftsavtale Stops at: 3 rounds / 100000 tokens Contacts: no external services Success: Minst ett tiltak som passerer validatoren ... ``` Kjører du med `--dimension-config`, kommer det en `Scoped to:`-linje til. Linjer for ting kjøringen ikke har — avgrensning, tallmål — utelates i stedet for å stå tomme: en tom linje ville lest som en beslutning ingen har tatt. `Contacts` er egress-erklæringen: en kjøring når aldri en ekstern tjeneste den ikke har navngitt her. `Stops at` er takene — systemet kjører aldri en ubegrenset løkke. ## Hva du får: oppgjøret Etter kjøringen svarer den for bestillingen, én linje per tilnærming: ``` Mandate outcome led-retrofit VALIDATED 30000 NOK LED-retrofit av kontorbelysning driftsavtale REJECTED claimed 240000 exceeds feasible 90000 own-proposal NOT EVALUATED budget exhausted before this approach was evaluated Validated: 1 of 3 approaches — best 30000 NOK (the outcome this run carries) ``` De tre statusene betyr forskjellige ting, og forskjellen er poenget: - **VALIDATED** — tallene holdt. Beløpet er det validatoren slapp gjennom. - **REJECTED** — tilnærmingen ble vurdert, og falt på tallene. Grunnen står der; det er den du kan gjøre noe med (ofte er den «regnet mot feil grunnlag», ikke «dårlig idé»). - **NOT EVALUATED** — kjøringen rakk den aldri. Den er **ikke** avvist, og den er ikke glemt. En tilnærming du bestilte forsvinner aldri i stillhet. Det er hele grunnen til at oppgjøret finnes. **Tilnærmingene summeres ikke.** Flere av dem angriper som regel samme kostnadslinje, så de er alternativer — ikke besparelser som legges oppå hverandre. Derfor står det *hvor mange som holdt* og *hvilken kjøringen bærer videre*, aldri en sum. (Dette ble oppdaget ved å faktisk kjøre den: tre tilnærminger mot samme linje ga «totalt 90 000», som ingen av dem kunne innfri.) ## Hva bestillingen ikke gjør - **Den overstyrer ikke validatoren.** Se ærlighetsmerkingen øverst. - **Den avgjør ikke om et tiltak skal gjennomføres.** Det gjør et menneske, etterpå — se [ekspert-svar.md](ekspert-svar.md). - **Den setter ikke et tallmål.** Sparemålet har ett hjem, målkonfigurasjonen (`--goals`, som gjelder porteføljemodus). To kopier av samme tall drifter fra hverandre, så oppdraget bærer hensikten i ord og gjengir tallet hvis det finnes. - **Den lagrer seg ikke som kunnskap.** Bestillingen er en instruks for én kjøring. Det som lærer systemet noe, er dommen du avgir etterpå. ## Hvis kjøringen skal spørre en ekstern tjeneste Skal agentene kunne slå opp i en tjeneste dere allerede har — et prisregister, målerdata, et avtaleregister — settes den opp med `--mcp-config`: ```json {"servers": [ {"name": "prisregister", "transport": "http", "url": "https://intern.example/mcp", "allowed_tools": ["lookup_unit_price"], "timeout_seconds": 15, "credential_env": "PRISREGISTER_TOKEN"} ]} ``` Tre ting er verdt å vite som bestiller: - **Du må navngi hvilke verktøy som er tillatt.** Tom liste er ikke lov. Uten det ville tjenesten selv bestemt hva agentene får lov til å kalle. - **Alt som vil bli kontaktet, står i kunngjøringen** — før første kall, på `Contacts:`-linja, med både servernavn og tillatte verktøy. En kjøring når aldri en tjeneste den ikke har navngitt. Det gjelder også når du ikke bruker `--mandate`. - **Passord og nøkler skal aldri i fila.** `credential_env` navngir en miljøvariabel; verdien leses derfra. Er variabelen ikke satt, blir kjøringen nektet — heller det enn å ringe tjenesten anonymt og få svar med feil tilgang. Uten `--mcp-config` gjøres ingen nettverkskall i det hele tatt.