feat(4b): AZURE-profilen leser miljøet sitt, ikke operatørens laptop
Endepunktet løses som første ikke-tomme av vårt eget PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT og Foundrys injiserte FOUNDRY_PROJECT_ENDPOINT — vårt vinner, fallbacken lar samme image kjøre hostet uten ekstra wiring. Presedensen gjelder verdier, ikke deklarasjoner. Credential velges av samme miljø: AzureCliCredential lokalt, ManagedIdentityCredential når FOUNDRY_HOSTING_ENVIRONMENT er satt, fordi containeren ikke har noen Azure CLI. Ikke DefaultAzureCredential — Learns MAF-veiledning navngir den spesifikke credentialen for å unngå probing. Load-bearing målt mot hele suiten, fire mutasjoner alle røde + grønn kontroll: detach credential-valget · presence i stedet for truthiness · detach fallbacken · snu presedensen. Fail-fast-testen var vakuøs først — vårt variabelnavn inneholder det injiserte som delstreng. De fire åpne azure.yaml-valgene lukket mot de to JSON-skjemaene og ført i docs/2026-08-13-fase4-azure-yaml-valg.md. Ingen azure.yaml skrevet (4d). 821 passed / 4 skipped. Ruff + format + mypy rene. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jk8tauXXAojNKC7Tzq7ziF
This commit is contained in:
parent
447c5a9d15
commit
63eec917d2
7 changed files with 373 additions and 12 deletions
125
docs/2026-08-13-fase4-azure-yaml-valg.md
Normal file
125
docs/2026-08-13-fase4-azure-yaml-valg.md
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
# Fase 4· — de fire åpne `azure.yaml`-valgene, lukket mot skjemaet
|
||||
|
||||
**Dato:** 2026-08-13 · **Metode:** de to autoritative JSON-skjemaene hentet og lest, ikke referert
|
||||
fra Learn-prosa · **Status:** beslutninger, ingen fil skrevet. `azure.yaml` skrives i 4d.
|
||||
|
||||
Spiken (`docs/2026-08-13-fase4-research-spike.md`) etterlot fire valg under «Ikke verifisert», med
|
||||
begrunnelsen at Learn og Microsofts eget sample er uenige og at autoriteten —
|
||||
`schemas/v1.0/azure.yaml.json` — ikke var lest. Den er lest nå.
|
||||
|
||||
## 0. Funnet som endrer hvordan de andre skal leses
|
||||
|
||||
**Skjemaet er PERMISSIVT, og kan derfor ikke avgjøre tre av de fire valgene.** Målt:
|
||||
|
||||
| Felt | Hva skjemaet faktisk sier |
|
||||
|---|---|
|
||||
| `host` | `type: string`, **ingen `enum`** — kun `examples`, der `azure.ai.agent` står |
|
||||
| `language` | `type: string`, **ingen `enum`** — `examples` inneholder BÅDE `python` og `docker` |
|
||||
| service-objektet | `additionalProperties: **true**` |
|
||||
|
||||
Et ukjent felt blir altså ikke avvist — det blir *ignorert*. Å skrive `environmentVariables:` ville
|
||||
ikke gitt en valideringsfeil; det ville gitt en fil som ser konfigurert ut og ikke er det. Det er en
|
||||
skarpere failure-mode enn den planen fryktet, og den er grunnen til at «samplet er fasit» ikke er
|
||||
godt nok som regel her.
|
||||
|
||||
**Den ekte autoriteten lå ett hopp videre.** `azure.yaml.json` delegerer agent-formen via `$ref`:
|
||||
|
||||
```
|
||||
"if": { "properties": { "host": { "const": "azure.ai.agent" } } },
|
||||
"then": { "required": ["project"],
|
||||
"allOf": [ { "$ref": ".../extensions/azure.ai.agents/schemas/azure.ai.agent.json" } ],
|
||||
"properties": { "config": { "deprecated": true, ... },
|
||||
"k8s": false, "apiVersion": false, "network": false } }
|
||||
```
|
||||
|
||||
Hentet: `azure.ai.agent.json` (http 200, 16 385 bytes). Den bærer `kind`, `protocols`,
|
||||
`codeConfiguration`, `container`, `startupCommand` — feltene Learn omtaler, og som hovedskjemaet
|
||||
ikke kjenner. To ting følger direkte: **`project` er påkrevd** for en hosted agent, og
|
||||
**`config:` er deprekert** (agent-innstillingene er flyttet opp på service-nivå).
|
||||
|
||||
## 1. Protokollversjon: `2.0.0`
|
||||
|
||||
Skjemaet lukker ikke valget, men det avgrenser det. `ProtocolVersionRecord`:
|
||||
|
||||
```json
|
||||
{"properties": {"protocol": {"type": "string"}, "version": {"type": "string"}},
|
||||
"required": ["protocol"], "additionalProperties": false}
|
||||
```
|
||||
|
||||
`version` er en fri streng **uten enum og uten default**, og er **valgfri**. Valget er altså vårt,
|
||||
og det er et valg mellom å pinne og å la plattformen bestemme.
|
||||
|
||||
**Vi pinner `2.0.0`, uttalt.** Grunnen er ikke at skjemaet sier det — det gjør det ikke — men at
|
||||
spikens §1.5 dokumenterer headere (`x-agent-user-id`, `x-agent-foundry-call-id`, og en gateway som
|
||||
dropper alt utenfor en allowlist) som er **egenskaper ved 2.0.0**. Kjører plattformen oss under en
|
||||
annen versjon enn den vi har lest kontrakten for, brytes antakelsene stille. Learn oppgir dessuten
|
||||
at 1.0.0 er deprekert med blokkering etter fristen. En utelatt versjon ville gjort dette til noe vi
|
||||
oppdager i drift; en pinnet gjør det til noe vi ser i diffen.
|
||||
|
||||
Skrives som `protocols: [{protocol: invocations, version: "2.0.0"}]` — **Invocations, ikke
|
||||
Responses**, som spikens §5 allerede avgjorde: `run_project` er ett kall med strukturert inn og ut,
|
||||
ikke en samtale.
|
||||
|
||||
## 2. Miljøvariabler: `env:`-map — dette lukkes AV skjemaet
|
||||
|
||||
MÅLT, i begge filer: `grep -c environmentVariables` → **0 og 0**. Ordet finnes ikke i noen av dem.
|
||||
`env` derimot er en deklarert service-property:
|
||||
|
||||
```json
|
||||
{"type": "object", "title": "Environment variables for the service",
|
||||
"description": "Optional. A map of environment variable names to values.
|
||||
Supports environment variable substitution.", "additionalProperties": {"type": "string"}}
|
||||
```
|
||||
|
||||
**`env:` er den eneste formen skjemaet kjenner.** `environmentVariables:` er ikke ulovlig (jf. §0),
|
||||
men ingenting validerer den og ingenting leser den. Dette er det ene av de fire valgene som er
|
||||
avgjort av autoriteten selv, ikke av vår vurdering.
|
||||
|
||||
Konsekvens for innholdet: `FOUNDRY_PROJECT_ENDPOINT` skal **ikke** redeklareres (spiken pkt. 2 —
|
||||
det risikerer å skygge plattformens egen verdi). Modelldeployment-navnet må derimot deklareres, det
|
||||
injiseres ikke.
|
||||
|
||||
## 3. `language: docker` — ikke `python`
|
||||
|
||||
Skjemaet tillater begge (ingen enum). Men `azure.ai.agent.json` gjør dem til to **gjensidig
|
||||
utelukkende deploy-modi**, og sier det rett ut i `CodeConfiguration`:
|
||||
|
||||
> «Code deploy configuration. **When present, the agent is deployed from source (ZIP) instead of a
|
||||
> container image.**» — påkrevd: `runtime` + `entryPoint`; `dependencyResolution` er
|
||||
> `bundled` eller `remote_build`.
|
||||
|
||||
Vi velger container, og grunnen er vår egen avhengighetsform: de to sikkerhetskomponentene er
|
||||
**git-pinnet via `[tool.uv.sources]`**, ikke publisert på PyPI (spikens §3 og §7.2). En
|
||||
source-ZIP-deploy overlater resolusjonen til en byggetjeneste vi ikke kontrollerer og som må nå
|
||||
`git.fromaitochitta.com` — og den formen bærer heller ikke `git` i base-imaget, som spikens §3
|
||||
målte at pip-veien trenger. Vår Dockerfile er nettopp det stedet den kunnskapen kan bo.
|
||||
|
||||
Altså: `language: docker`, **ingen `codeConfiguration`**. `entryPoint`-uenigheten i spikens tabell
|
||||
(`main.py` vs `["python", "main.py"]`) faller bort med den — feltet tilhører kun ZIP-modusen, og er
|
||||
`type: string`, ikke en liste, i skjemaet.
|
||||
|
||||
## 4. Wrapper-form: IKKE avgjort her — og det er en måling, ikke en utsettelse
|
||||
|
||||
Skjemaet har ingenting å si om dette; det er et kodespørsmål. Men det ene alternativet er MÅLT
|
||||
utilgjengelig i dag:
|
||||
|
||||
```
|
||||
agent_framework_foundry_hosting -> ModuleNotFoundError
|
||||
agent_framework.foundry -> IMPORT OK, 27 eksporter, 0 med "Host"/"Server" i navnet
|
||||
agent_framework_foundry -> 1.8.2, 0 host-klasser
|
||||
```
|
||||
|
||||
`InvocationsHostServer` finnes altså ikke i det installerte treet, og pakka som skal bære den har
|
||||
ingen stabil release (spikens pkt. 8). **Valget kan ikke tas før pakka er installert og målt**, og
|
||||
det hører uansett til 4c — som spikens §5 allerede har vist er et *signaturproblem*
|
||||
(`run_project` tar `project_id` + to påkrevde keyword-argumenter og gir en frozen `RunResult`),
|
||||
ikke et grafproblem. Ført videre som åpent, med en kjørbar grunn.
|
||||
|
||||
## Sidefunn, ikke handlet på
|
||||
|
||||
`agent_framework.foundry` eksporterer **`AnthropicFoundryClient`** og `RawAnthropicFoundryClient`.
|
||||
STATEs 1b-blokk slår fast at `FoundryChatClient` ikke kan binde en Claude-deployment fordi Claude på
|
||||
Foundry er en tredje klientflate (`/anthropic/v1/messages`, målt 13.08). Det står ved lag — men MAF
|
||||
ser altså ut til å shippe en egen klient for nettopp den flaten. Det endrer potensielt 1b-valget
|
||||
«Microsoft-solgt modell → ren konfig», og bør måles før 1b, ikke under. **Ikke verifisert:** at
|
||||
klassen faktisk virker mot en Claude-deployment, og at den komponerer med `backends.py`-sømmen.
|
||||
Loading…
Add table
Add a link
Reference in a new issue