portfolio-optimiser/docs/2026-08-13-fase4-research-spike.md
Kjell Tore Guttormsen 447c5a9d15 docs(4·): containeren er bygget — og wheelen er ikke installerbar alene
Fullfører spikens siste måling etter at docker-tillatelsen kom på plass.

7.1 — `docker build --platform linux/amd64` grønn på python:3.12-slim-bookworm.
`uv sync --frozen` resolverte inne i containeren, inkludert begge git-pinnene,
og siste lag ga `import OK`. Det lukker gapet uv-resolusjonen ikke kunne lukke:
at avhengighetene LØSER for linux beviser ikke at koden KJØRER der.

7.2 — Andre måling bygde wheelen, SLETTET kilden, og installerte kun wheelen.
Den feilet: `llm-ingestion-guard was not found in the package registry`.
Wheelens metadata bærer de to avhengighetene som BARE NAVN — [tool.uv.sources]
er uv-konfig og reiser ikke med wheelen, og navnene finnes ikke på PyPI. En
nedlaster som får et wheel (f.eks. fra release-objektet fase 3 skal lage)
treffer denne veggen. Med direct references ved siden av: 65 pakker, exit 0.

Dette er den skarpeste friksjonskanten spiken fant, og ingen hadde spurt om den.

7.3 — Samme bygg beviste fase 4a i container: shared_root() peker på
site-packages/portfolio_optimiser/_shared, 80 filer, persona-skillen lesbar —
uten arbeidstre, siden /build var slettet før installasjonen. Invarianten er
dermed målt i situasjonen den ble bygget for, ikke bare i enhetstest.

Byggekonteksten er `git archive HEAD` (311 sporede filer) — det en fremmed
faktisk laster ned, ikke arbeidstreet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jk8tauXXAojNKC7Tzq7ziF
2026-08-13 21:57:40 +02:00

438 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Fase 4· — research-spike: hostingkontrakten for Foundry Agent Service
**Dato:** 2026-08-13 · **Commit ved måling:** `f5ec8c8` · **Metode:** agent-team, fire parallelle
spor, alle Opus/xhigh · **Leveranse:** svar som kommandoer og siterte kilder, aldri vurderinger.
Denne rapporten åpner fase 4 i den kanoniske planen. Den bygger ingen produksjonskode og rører
ikke `shared/`. Alt som står her er enten kjørt på denne maskinen eller sitert fra Microsoft Learn
med URL. Det som ikke lot seg verifisere står under **Ikke verifisert** — ikke i brødteksten.
---
## 0. Sammendrag for den som bare leser ett avsnitt
Alle fire spørsmål er besvart med kjørte kommandoer og siterte kilder, og containeren er bygget på
`linux/amd64` (§7). Underveis kom det ett funn ingen hadde spurt om: **wheelen er ikke installerbar
alene** — dens metadata bærer to avhengigheter som bare navn, og de finnes ikke på PyPI (§7.2). Det
er den skarpeste friksjonskanten spiken fant.
Spiken felte **tre premisser i planen**:
| Premiss i planen | Dom |
|---|---|
| «`azd`-utvidelsen heter enten `microsoft.foundry` eller `azure.ai.agents` — én er utdatert» | **Feil.** Begge er gjeldende; den ene er en meta-pakke over den andre |
| «Foundry injiserer `FOUNDRY_PROJECT_ENDPOINT`, `AZURE_AI_MODEL_DEPLOYMENT_NAME` og `APPLICATIONINSIGHTS_CONNECTION_STRING`» | **To av tre.** `AZURE_AI_MODEL_DEPLOYMENT_NAME` injiseres IKKE — den deklarerer vi selv |
| «`docker build` og `azd ai agent run` mot `localhost:8088` er testbare UTEN Azure» | **Feil for `azd ai agent run`.** Den krever `azd auth login` og provisjonerte ressurser |
Alt materialet er hentet mot det gjeldende hostingbackendet, ikke det gamle preview-et. Se §8 for
hvorfor det skillet betyr noe når man leser eldre oppskrifter.
---
## 1. Hostingkontrakten
### 1.1 Runtime-kontrakten er kort og eksplisitt
Kilde: <https://learn.microsoft.com/azure/foundry/agents/concepts/hosted-agent-contract>
| Krav | Detalj (sitert) |
|---|---|
| Port | «Listen on port 8088 … HTTP/1.1, plain HTTP. The platform terminates TLS.» |
| Helse | «Return `200 OK` from `GET /readiness`.» |
| Protokoll | «Serve at least one of `POST /responses` or `POST /invocations`.» |
| Miljø | «Read the variables the platform injects at startup.» |
| Avslutning | «Flush writes and close connections on `SIGTERM`.» |
Bind-adresse er `0.0.0.0`, og porten kan overstyres med `PORT`. `/readiness` implementeres ikke av
oss: «The protocol libraries automatically expose a `/readiness` endpoint for platform health
checks. You don't need to implement this yourself.»
### 1.2 Filsettet
Learn oppgir intet normativt «required files»-sett. Det som finnes er hva `azd ai agent init`
skaper, og hva Microsofts egen MAF-sample faktisk inneholder.
Scaffold (<https://learn.microsoft.com/azure/foundry/agents/how-to/init-agent-project>):
```
.
|-- azure.yaml # Unified azd project and hosted agent configuration
|-- src/
| \-- <agent-name>/
| |-- Dockerfile # Container build definition
| \-- ... # Agent source code
|-- .azure/ # Environment configuration
\-- infra/ # Optional IaC, created only after you eject infrastructure
```
**Agent-manifest er avviklet** — dette er en bruddendring mot enhver eldre oppskrift:
> «Agent manifests (`agent.manifest.yaml`) and standalone agent definitions (`agent.yaml`) are
> deprecated. As of the Foundry `azd` extensions (`azure.ai.agents` 1.0.0-beta.1), all hosted agent
> configuration lives in a single `azure.yaml`.»
Microsofts referansesample for Python/MAF bærer i `src/<agent>/`: `.azdignore`, `.dockerignore`,
`.env.example`, `Dockerfile`, `main.py`, `requirements.txt`. Merk: **ingen `pyproject.toml`** — den
bruker `requirements.txt`. Det er relevant for oss, se §3.
Samplets Dockerfile, ordrett
(<https://raw.githubusercontent.com/microsoft-foundry/foundry-samples/main/samples/python/hosted-agents/agent-framework/responses/01-basic/src/agent-framework-agent-basic-responses/Dockerfile>):
```dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY . user_agent/
WORKDIR /app/user_agent
RUN if [ -f requirements.txt ]; then pip install -r requirements.txt; else echo "No requirements.txt found"; fi
EXPOSE 8088
CMD ["python", "main.py"]
```
At Microsofts egen sample lander på `python:3.12-slim` er verdt å merke seg mot §4: det er samme
base-image vår egen resolusjon peker på, av uavhengige grunner.
### 1.3 `azure.yaml` — skjema og det uavklarte
`$schema`-linja:
`# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json`
`host:`-verdien for en hosted agent er **`azure.ai.agent`** («Must be `azure.ai.agent`»).
Sentrale felter (<https://learn.microsoft.com/azure/foundry/agents/concepts/azure-yaml-reference>):
`kind: hosted`, `project` (sti til kildekatalog), `language`, `uses`, `protocols`, `env`,
`container`, `startupCommand`, `codeConfiguration`, `image`.
**Learn og Microsofts eget sample er uenige på fire punkter.** Dette er ikke en detalj — det er
forskjellen mellom en `azure.yaml` som virker og en som avvises:
| Punkt | Learn-referansen | Samplet (det `azd ai agent init -m` faktisk adopterer) |
|---|---|---|
| Byggespråk | `language: docker` | `language: python` + `codeConfiguration` |
| Miljøvariabler | `env:` som map | `environmentVariables:` som liste av `{name, value}` |
| Entrypoint | `entryPoint: main.py` | også `entryPoint: ["python", "main.py"]` i en annen artikkel |
| Protokollversjon | `2.0.0` i azure.yaml-eksempler | `1.0.0` i SDK/REST-eksempler |
Anbefaling: **bruk samplet som fasit**, fordi det er fila `azd ai agent init -m` kopierer. Men
protokollversjonen må avklares før vi skriver vår egen — se **Ikke verifisert** pkt. 4.
### 1.4 Container-krav
`linux/amd64` er bekreftet påkrevd
(<https://learn.microsoft.com/azure/foundry/agents/how-to/deploy-hosted-agent>):
> «The hosting platform requires x86_64 (linux/amd64) container images. If you build on Apple
> Silicon or other ARM-based machines, use `docker build --platform linux/amd64 .` to avoid
> producing an incompatible ARM image.»
Planens observasjon står: på operatørens Intel-Mac er dette maskinens egen arkitektur, og vi har
målt at colima-VM-en rapporterer `linux/x86_64` (§6). Ingen emulering.
**CPU/minne motsier seg selv i Learn.** Referansesiden sier fritt intervall («`cpu` from `"0.25"`
up to `"4.0"`, and `memory` from `0.5Gi` up to `8.0Gi`»), mens konseptsiden gir tre faste tiers
(0.5 vCPU/1 GiB, 1/2, 2/4). Feilmeldingen avgjør tolkningen: `400 bad_request` med «CPU and Memory
must be specified as a valid resource tier». **Bruk tier-tabellen.**
Dokumenterte tidsgrenser: idle-timeout 15 minutter, sesjonslevetid maks 30 dager, diskbudsjett
opptil 20 GiB ved ≥1 vCPU hvorav ~20 % er systemreservert.
### 1.5 Headere under protokoll 2.0.0
Plattformen injiserer `x-agent-user-id` (per bruker) og `x-agent-foundry-call-id` (per request,
skal videresendes uendret på utgående Foundry-kall). Gatewayen **dropper alt annet enn en
allowlist** — `Authorization`, `Host`, `Cookie` og `x-forwarded-*` kommer aldri fram; egne headere
må prefikses `x-client-`. Begge de injiserte er «not guaranteed when you run locally», så koden må
tåle at de mangler.
---
## 2. `azd`-utvidelsens navn — planens premiss var feil
Planen antok at ett av navnene var utdatert. Målt mot azds offisielle register
(`https://aka.ms/azd/extensions/registry`, som redirecter til
`raw.githubusercontent.com/Azure/azure-dev/refs/heads/main/cli/azd/extensions/registry.json`,
451 555 bytes — byte-identisk med repo-URL-en, altså samme fil): **begge ID-ene finnes samtidig, og
de gjør forskjellige ting.**
| ID | Rolle | Siste versjon | Kommandogruppe |
|---|---|---|---|
| `microsoft.foundry` | Meta-pakke uten egne kommandoer og uten binærartefakter | 1.0.0-beta.2 | — |
| `azure.ai.agents` | Den faktiske utvidelsen; eier `service-target`-provideren «Deploys agents to the Foundry Agent Service» | 1.0.0-beta.9 (utgitt 2026-08-06) | `azd ai agent` |
Learn sier det selv rett ut
(<https://learn.microsoft.com/azure/foundry/agents/how-to/install-cli-foundry-extensions>):
> «The `microsoft.foundry` package is a thin meta-package that doesn't contribute its own commands.
> Installing it pulls in every individual extension, which is the recommended starting point.»
**Det som faktisk henger etter i doc-en er ikke ID-navnet, men versjonskravet.** Flere Learn-sider
sier `azd` 1.25.2 eller senere; registeret krever `>=1.27.1` for begge utvidelsene. Vi installerte
1.31.0 (§6), så vi ligger over.
`darwin/amd64`-artefaktet finnes for `azure.ai.agents` 1.0.0-beta.9 (sha256
`f0750469a17c7370534db21d5542eb9241f2ffc1093361bf373b5ef71ff43c1f`) — altså støttet på denne
maskinen.
Kommandoene, ordrett fra Learn:
```bash
azd ext install microsoft.foundry # meta-pakke, anbefalt start
azd ext install azure.ai.agents # bare agent-flaten (drar inn azure.ai.inspector)
azd ext list
azd ai agent version
```
`azd extension` og `azd ext` er samme kommando — verifisert i azds kildekode
(`cli/azd/cmd/extension.go`, linje 50: `Aliases: []string{"ext"},`), ikke bare i doc.
---
## 3. Avhengighetsformen i container — direct references, ingen publisering
Spørsmålet var om `[tool.uv.sources]`-git-pinnene overlever inn i en container, siden de ikke
finnes i wheel-metadata. **Svaret er ja, i begge pakkeverktøy, uten publisering og uten auth.**
| Måling | Kommando | Exit |
|---|---|---|
| uv resolverer direct references | `uv pip compile req-direct-min.txt --python-version 3.12 --python-platform linux` | 0 |
| pip gjør det samme | `pip install --dry-run --report … -r req-direct-min.txt` | 0 |
| Anonym git-lesing virker | `env -u GIT_ASKPASS GIT_TERMINAL_PROMPT=0 git ls-remote https://git.fromaitochitta.com/open/llm-ingestion-okf.git v0.3.2` | 0 |
At **pip** klarer det er poenget: en Dockerfile er ikke bundet til `uv`. uv oppgraderer dessuten
tag → commit-SHA i outputen, så formen er selv-pinnende.
Alle tre pakkenavn er ledige på PyPI (HTTP 404 på `/simple/`), så publisering ville vært mulig —
men er unødvendig, og ville lagt en release-forpliktelse på to sikkerhetskomponenter som i dag er
tag-pinnet med vilje.
**Én felle er målt.** Default-eksporten fra lockfila produserer en fil pip **avviser**:
```
ERROR: Can't verify hashes for these requirements because we don't have a way
to hash version control repositories
```
pips hash-modus er alt-eller-ingenting, og en git-URL kan ikke hashes. Den målte veien rundt, som
beholder hash-verifisering for de 64 PyPI-pakkene:
```bash
uv export --frozen --format requirements.txt --no-dev --no-emit-project -o requirements.txt
grep -v '^llm-ingestion' requirements.txt > requirements-pypi.txt # hashet
grep '^llm-ingestion' requirements.txt > requirements-git.txt # commit-pinnet
```
Base-imaget må da ha `git` installert. `-slim`-variantene har det ikke.
**Bygg fra eksporten, ikke fra `pyproject.toml`.** Fersk resolusjon velger
`agent-framework-core==1.13.0` og `mcp==2.0.0`, mens `uv.lock` pinner `1.9.0` / `1.28.0`. Begge er
lovlige innenfor spennet, men en container bygget fra `pyproject.toml` ville kjørt andre versjoner
enn utviklermaskinen — og MAF-pinnen `<2` er tosidig nettopp fordi privat-API-premissene må
re-verifiseres ved bump.
---
## 4. Base-image — 3.10 til 3.13, aldri 3.14
Resolusjonsmatrise mot `x86_64-unknown-linux-gnu`, hele `[project.dependencies]`:
| Python | Fersk resolusjon | Med wheel-krav på numpy | numpy | agent-framework-core |
|---|---|---|---|---|
| 3.10 | ✅ | ✅ | 2.2.6 | 1.13.0 |
| 3.11 | ✅ | ✅ | 2.2.6 | 1.13.0 |
| 3.12 | ✅ | ✅ | 2.2.6 | 1.13.0 |
| 3.13 | ✅ | ✅ | 2.2.6 | 1.13.0 |
| 3.14 | ✅ | ❌ | kun via sdist | 1.13.0 |
**Den ferske resolusjonen alene er villedende, og det er hele funnet.** Alle fem «resolverer»,
fordi numpy 2.2.6 har en sdist. Men numpy 2.2.6 har manylinux-x86_64-hjul kun for cp310cp313 —
ingen cp314. På 3.14 ville containeren kompilert numpy fra kilde, altså dratt inn en full
byggekjede og en byggetid ingen har budsjettert. `--only-binary numpy` gjør det til en hard feil i
stedet for en skjult kostnad:
```
× No solution found when resolving dependencies:
╰─▶ … numpy>=2.0.0,<=2.2.6 has no usable wheels …
your requirements are unsatisfiable.
```
Dette er `numpy<2.3`-taket i `pyproject.toml` som binder. Taket står der av to andre grunner
(3.10-støtte og mypys PEP 695-parsing), og 3.14-utfallet er en bivirkning av dem.
**Valg: `python:3.12-slim-bookworm`** — repoet pinner `.python-version` = 3.12, det ligger midt i
det lovlige båndet, og Microsofts egen MAF-sample bruker `python:3.12-slim` (§1.2).
---
## 5. `Workflow.as_agent()` — virker, men eksponerer feil ting
Målt mot det installerte (`agent-framework-core` 1.9.0), ikke mot dokumentasjonen:
- `fresh_workflow(...)` returnerer en ekte `agent_framework._workflows._workflow.Workflow`
- `.as_agent()` konstruerer en `WorkflowAgent(BaseAgent)` som tilfredsstiller `SupportsAgentRun`
- `await ag.run(...)` **kjører**, og returnerer proposer- og checker-meldingene
Learn bekrefter at dette er den offisielle mekanismen
(<https://learn.microsoft.com/agent-framework/hosting/foundry-hosted-agent>):
> «you can expose an `Agent`, including a workflow wrapped with `Workflow.as_agent()`, through the
> Foundry Responses or Invocations protocol with minimal code.»
**Og likevel er svaret «wrapper», ikke «direkte».** `fresh_workflow` er steg 3 av åtte i
`run_project` (`src/portfolio_optimiser/run.py:554`). Validatoren, kostbaseline-forankringen,
provenance-stempelet, checker-gaten, ledgeren og læringssløyfa ligger alle **utenfor**
`Workflow`-grafen. En hosted agent bygget på `as_agent()` alene ville servert ugatede agent-forslag
— altså brutt repoets egen invariant om at den deterministiske validatoren er obligatorisk og
blokkerende.
Signaturgapet er konkret: hosting-flaten tar `str`/`Message` inn og gir `AgentResponse` ut;
`run_project` tar `project_id` pluss to påkrevde keyword-argumenter uten default (`docs_dir`,
`verdict_input`) og gir en frozen `RunResult`-dataclass. **Fase 4c er derfor et signaturproblem,
ikke et grafproblem.**
To detaljer med konsekvens:
1. `AgentResponse.text` **konkatenerer** proposer + checker + orkestratorens sluttnotis til én
streng. Dagens kode skiller dem på `author_name` (`run.py:330`). En hosted flate som returnerer
`.text` ville slått de to falsifisererne sammen til én tekst.
2. `fresh_workflow` er en factory nettopp fordi et gjenbrukt workflow akkumulerer tråd på tvers av
kall. En hostet agent er per definisjon ett langlevd objekt som betjener mange forespørsler.
**Dette er den største uavklarte risikoen spiken fant**, og må måles før 4c-designet låses.
Dette bekrefter planens 4c-valg: **Invocations, ikke Responses.** `run_project` er ett kall med
strukturert inn og strukturert ut, ikke en samtale. Learn plasserer Invocations på «custom
payloads, non-conversational processing».
---
## 6. Miljøet — hva som ble reparert på maskinen
Verktøykjeden manglet ved oppstart. Målt før:
| Verktøy | Før | Etter |
|---|---|---|
| `az` | 2.84.0 (var installert) | uendret |
| `azd` | not found | 1.31.0 (formelen heter `azure-dev`) |
| `docker` | not found | klient 29.7.2 / server 29.5.2 |
| daemon | ingen | colima 0.10.3 → `linux/x86_64`, 6 CPU, 10 GB |
Docker Desktop-casken var registrert som installert (4.50.0) mens `/Applications/Docker.app` ikke
fantes og Caskroom-katalogen var 0 B — en foreldet brew-oppføring. **colima ble valgt framfor
Docker Desktop** fordi Desktop krever GUI-oppstart og admin-passord, mens colima kjører fra
terminalen. På en Intel-Mac er colima-VM-en `linux/amd64` nativt.
Én etterlatenskap måtte ryddes: `~/.docker/config.json` pekte på `credsStore: "desktop"`, en
credential-helper som ikke lenger fantes, og som feilet ethvert image-oppslag. `auths` var tom, så
linja ble fjernet (backup: `~/.docker/config.json.bak-20260813-213134`).
---
## 7. Containeren er bygget — to målinger
Byggekonteksten er `git archive HEAD` (311 sporede filer, 3,7 MB), altså **det en fremmed faktisk
laster ned** — ikke arbeidstreet med `.venv` og lokale artefakter.
### 7.1 Bygger og importerer på `linux/amd64`
```bash
docker build --platform linux/amd64 --build-arg PYVER=3.12 -f Dockerfile.measure -t po-measure:py312 .
```
Exit 0. `uv sync --frozen --no-dev` resolverte inne i containeren — inkludert de to git-pinnede
avhengighetene — og siste lag ga `import OK`. Det lukker gapet §3/§4 ikke kunne lukke: uv-resolusjon
viser at avhengighetene *løser* for linux; dette viser at koden *importerer og kjører* der.
### 7.2 Wheelen er IKKE installerbar alene — målt
Andre måling bygde wheelen, **slettet kilden**, og installerte kun wheelen i et rent miljø. Den
feilet:
```
× No solution found when resolving dependencies:
╰─▶ Because llm-ingestion-guard was not found in the package registry
and portfolio-optimiser==1.0.0 depends on llm-ingestion-guard …
your requirements are unsatisfiable.
```
**Dette er den viktigste friksjonsobservasjonen i hele spiken.** Wheelens metadata bærer de to
avhengighetene som *bare navn*, fordi `[tool.uv.sources]` er uv-konfigurasjon og ikke reiser med
wheelen. Navnene finnes ikke på PyPI (§3). En nedlaster som får et wheel — f.eks. fra et
release-objekt, som er fase 3-raden — treffer denne veggen med mindre de to git-kravene oppgis ved
siden av. Det må stå i installasjonsdokumentasjonen, eller løses ved publisering.
Med direct references ved siden av virker det:
```bash
uv pip install /dist/*.whl \
"llm-ingestion-okf @ git+https://git.fromaitochitta.com/open/llm-ingestion-okf.git@v0.3.2" \
"llm-ingestion-guard @ git+https://git.fromaitochitta.com/open/llm-ingestion-pipeline-security.git@v0.3.4"
```
`Installed 65 packages`, exit 0.
### 7.3 Fase 4a holder i container
Samme bygg verifiserte pakkede data uten arbeidstre — `/build` var slettet før installasjonen:
```
pakke: /app/venv/lib/python3.12/site-packages/portfolio_optimiser
shared_root: /app/venv/lib/python3.12/site-packages/portfolio_optimiser/_shared
filer under shared_root: 80
PAKKEDE DATA OK
```
`shared/skills/expert-reviewer/SKILL.md` er lesbar derfra. Fase 4a-invarianten — wheelen bærer
`shared/` som pakkede data, arbeidstreet er kun en overstyring — er dermed målt i den situasjonen
den ble bygget for, ikke bare i enhetstest.
---
## Ikke verifisert
1. **Lokal kjøring uten Azure.** Planen og STATE påsto at `azd ai agent run` mot `localhost:8088`
er testbart uten Azure. Learn sier det motsatte: kommandoen krever `azd auth login`, henter
miljøvariabler fra et azd-miljø, og «The local agent still calls cloud-hosted models».
`--local` sparer *deploy*, ikke *Azure*. **Dette er kostnadsrelevant og bør inn i planen.**
2. **`AZURE_AI_MODEL_DEPLOYMENT_NAME` injiseres ikke.** Bekreftet injisert:
`FOUNDRY_PROJECT_ENDPOINT`, `FOUNDRY_PROJECT_ARM_ID`, `FOUNDRY_AGENT_NAME`,
`FOUNDRY_AGENT_VERSION`, `FOUNDRY_AGENT_SESSION_ID`, `FOUNDRY_AGENT_ID`,
`APPLICATIONINSIGHTS_CONNECTION_STRING`, `FOUNDRY_HOSTING_ENVIRONMENT`, `HOME`, `PORT`.
Modelldeployment-navnet deklarerer vi selv. `FOUNDRY_PROJECT_ENDPOINT` skal **ikke** redeklareres
i `azure.yaml` — det risikerer å skygge plattformens verdi. Kilden til vår antakelse var
MAF-hostingsiden, som motsier plattformdoksettet og Microsofts eget sample.
3. **Rollen for deploy er `Foundry Project Manager` på prosjekt-scope**, ikke `Foundry User` som
1b-forberedelsen bruker. De to er ulike oppgaver (kjøre modellkall vs. deploye en agent) og bør
ikke blandes.
4. **Protokollversjon i `azure.yaml`: `1.0.0` eller `2.0.0`.** Learn viser begge i samme doksett.
Container-protokoll 2.0.0 er separat fra protokoll-versjonsfeltet, og 1.0.0 er deprekert med
blokkering etter fristen. Må avklares mot JSON-skjemaet før vi skriver fila.
5. **`env:`-map vs `environmentVariables:`-liste**, og **`language: docker` vs `language: python`**
— Learn og samplet er uenige, og skjemafila er ikke lest.
6. **Påkrevd vs valgfritt felt-for-felt** for `azure.ai.agent`-tjenesten. Learns tabell har ingen
Required-kolonne; autoriteten er `schemas/v1.0/azure.yaml.json`, som ikke er lest.
7. **Ikke-root-krav** finnes ikke dokumentert, og Microsofts sample kjører som root uten `USER`.
Fravær av dokumentasjon er ikke en garanti.
8. **`agent-framework-foundry-hosting` er ikke installert**, og import-stien er omstridt:
Learn bruker `agent_framework_foundry_hosting`, et MAF-sample bruker `agent_framework.foundry`.
Vår installerte 1.8.2 eksporterer ingen av host-server-klassene. Siste PyPI-versjon er
`1.0.0b260730`**ingen stabil release finnes.**
9. **Kompatibilitet** mellom hosting-pakka og `agent-framework-core` 1.9.0 er ikke testet.
10. **Foundry Agent Service i Norway East** — regionslista inkluderer den, men modell- og
kvotedekning per region er ikke sjekket.
---
## 8. Hvorfor eldre oppskrifter ikke kan brukes
Foundry har byttet hostingbackend. Det gamle public-preview-backendet er under avvikling
(<https://learn.microsoft.com/azure/foundry/agents/how-to/migrate-hosted-agent-preview>):
> «The initial public preview hosting backend is retiring. … Existing agent deployments on the old
> backend aren't migrated automatically and are supported only until August 20, 2026.»
**Dette er ingen frist for oss** — vi har aldri deployet, og har derfor ingenting å migrere. Det er
en *dateringsregel*: en blogg, oppskrift eller Learn-side skrevet mot det gamle backendet beskriver
en flate som ikke lenger er den vi bygger mot, uansett hvor godt den er skrevet. Konkret er tre
ting fra den epoken allerede ugyldige: `agent.manifest.yaml`/`agent.yaml` (§1.2),
`Foundry-Features: HostedAgents=V1Preview`-headeren, og protokollversjonsformatet `"v1"`.
Alt materialet i denne rapporten er hentet mot det gjeldende backendet. Det er også grunnen til at
rapporten siterer URL og dato på hver påstand i stedet for å oppsummere: neste økt skal kunne se
hva som var sant da, ikke bare hva jeg konkluderte.