Gå til indhold

HTTP-API

API-kontrakten

Alt, klienten gør, er almindelige HTTP-kald, du selv kan foretage. Denne side er kontrakten: hvordan du autentificerer, hvad der kommer tilbage, hvad fejlene betyder, og hvilket endpoint der gør hvad.

Base-URL

Hver sti herunder er relativ til dette origin. Behandl værten som en variabel — den flytter til et eget domæne — og hold den ét sted i din konfiguration frem for spredt ud i din kode.

base URL
https://pfmem-api.packagefactory.dk

To måder at autentificere på

En bearer-API-nøgle

Alt andet. Nøglen opløses på serveren til en konto, et arbejdsområde, en rolle og et sæt verber. Læg den aldrig i en query-streng, i en fejlrapport eller i noget, der registrerer en URL.

request header
authorization: Bearer mk_live_...

En session-cookie

Bruges af ruterne til oprettelse og log ind samt af de to kontoruter — den, der udsteder en kontos første master-nøgle, og den, der giver en browser dens CSRF-token. Det er browserens mekanisme, og det er den eneste vej til det endpoint, der udsteder den første nøgle, for før det kald findes der ingen nøgle at autentificere med.

CSRF-tokenet

Et kald, der ændrer tilstand og er autentificeret med en cookie, skal gentage sessionens token i en header, fordi en browser selv vedhæfter en cookie til et kald på tværs af sites. En kalder, der bruger en API-nøgle, har ikke brug for noget af dette: en browser vedhæfter aldrig en nøgle af sig selv, så en nøgle kan ikke bruges på tværs af sites.

session-authenticated writes
GET  /api/v2/account/csrf-token   → { "csrf_token": "...", "header_name": "x-csrf-token" }
POST /api/v2/account/master-key   → x-csrf-token: <that token>

Konvolutten

Hvert endpoint svarer i en af to former. Et vellykket svar bærer et request-id og et data-objekt; en fejl bærer et error-objekt med en stabil kode, en besked til mennesker og en type.

success
{
  "request_id": "23ba77f0c6474ccb8dc5d65d1a44d069",
  "data": { }
}
failure
{
  "error": {
    "code": "version_conflict",
    "message": "…",
    "type": "invalid_request_error"
  }
}

API'et returnerer aldrig 200 ved en fejl. Er statussen 200, findes der et data-objekt, og findes der et error-objekt, siger statussen det også.

Forgren på koden, aldrig på beskeden. Vis aldrig en rå kode til et menneske — oversæt den til tekst, de kan handle på.

Læg request-id'et et sted, det kan kopieres fra, på enhver fejlskærm. Det er det første, support beder om, og tjenesten logger den samme værdi.

Statuskoder

Fem koder dækker hver fejl. Kun to af dem er værd at prøve igen: et nyt forsøg på de tre andre sender det samme afviste kald en gang til.

Statuskoder, deres betydning og hvordan de håndteres
KodeBetydningSådan håndteres den
401Manglende eller ugyldig nøgle.Bed om en nøgle, eller log ind igen. Prøv aldrig igen.
403Nøglen mangler verbet, eller målet ligger uden for dens rækkevidde.Navngiv den manglende rettighed. Prøv aldrig igen.
422Kaldet fejlede valideringen.Vis fejlen ved det felt, den hører til. Prøv aldrig igen.
429En kvote eller en rate limit blev nået.Vis grænsen, og hvornår den nulstilles. Prøv igen efter en pause.
503Noget, MemoryAgent afhænger af, er utilgængeligt. Kaldet blev ikke behandlet; prøv igen.Forbigående. Prøv igen med stigende ventetid.

Nøgleniveauer

Præfikset fortæller dig, hvad en nøgle kan nå, før du bruger den. En liste over nøgler returnerer aldrig en hemmelighed — kun et præfiks, en betegnelse og en dato — fordi en hemmelighed vises én gang, i det øjeblik den udstedes.

Nøglepræfikser, niveauer, rækkevidde og verber
PræfiksNiveauRækkeviddeVerber
mk_live_masterHvert arbejdsområde i kontoen.read · write · delete
tk_live_tenantÉt arbejdsområde.read · write · delete
rk_live_tenant_roleÉt arbejdsområde, én rolle.En reader må læse; en writer må læse og skrive.

Roller

En rollenøgle bærer en rolle, og rollen afgør, hvad nøglen må nå inde i sit arbejdsområde. Vælg den snævreste, der stadig løser opgaven: en nøgle er der, hvor en fejl bliver indeholdt. Fire af de seks er bundet til én person eller agent, og en nøgle med en af dem udstedes med det subjekt, den handler for.

Roller, hvad hver især læser og skriver, og om den nævner et subjekt
RolleLæserSkriverNævner et subjekt
adminHele arbejdsområdet.Alt, og det er den eneste rolle, der må slette.Nej
writerHele arbejdsområdet.Som én navngiven person.Ja
readerHele arbejdsområdet.Intet. Brug den til dashboards og rapporter.Nej
agentKun det, denne agent selv har skrevet.Som sig selv. Brug den, når én agent ikke må se en andens arbejde.Ja
shared-agentHele arbejdsområdet.Som sig selv. Brug den til et hold af agenter, der deler én sag, mens hver enkelt forbliver sporbar.Ja
restricted-userKun den ene persons erindringer.Som den person.Ja

Hukommelse

Den flade, din applikation kalder, autentificeret med en bearer-nøgle. Indlæsning er asynkron, så en hukommelse under behandling er en rigtig tilstand i din grænseflade og ikke et særtilfælde.

Hukommelsesendpoints
EndpointFormål
POST /api/v2/memory/addGemmer en samtale. Returnerer et task-id; udtrækningen kører bagefter.
POST /api/v2/memory/searchRangerer resultater ved at kombinere betydning og præcis ordlyd.
POST /api/v2/memory/getViser et subjekts hukommelser, filtreret og pagineret.
POST /api/v2/memory/recallSaml en færdig kontekstblok: personaen, scenarierne og de bedste hukommelser, under et token-budget.
POST /api/v2/memory/editRetter én gemt hukommelse. Den indekseres på ny, så senere søgninger rammer den nye ordlyd.
POST /api/v2/memory/deleteSletter udtrukne hukommelser. Den underliggende samtale bevares.
POST /api/v2/memory/flushKører en sessions ventende udtrækning nu.
POST /api/v2/memory/trail/listLæs arbejdsområdets ændringsspor: enhver registreret ændring af dets hukommelser, nyeste først, kædet med hashes.
POST /api/v2/memory/procedures/*Procedurel hukommelse: skriv, læs, versionér, tag ud af brug, list og søg i de procedurer, et arbejdsområde holder. Den har sit eget afsnit nedenfor.
POST /api/v2/meFortæller, hvad den nøgle, du sidder med, står for: dens arbejdsområde, niveau, rolle, verber og det subjekt, den eventuelt er bundet til.

Sådan ser en forespørgsel og et svar ud

Oversigterne ovenfor siger, hvad hvert kald er til. Disse siger, hvad du sender, og hvad der kommer tilbage — for den skrivning, enhver klient laver først, og den læsning, den laver derefter.

At gemme er asynkront: svaret er en opgave, ikke en erindring. Portionen udtrækkes i baggrunden, og det id, du angiver, gør en gentagelse af det samme kald ufarlig.

POST /api/v2/memory/add
{
  "mode": "chat",
  "session_id": "s_17",
  "user_id": "[email protected]",
  "idempotency_key": "add-s17-0001",
  "messages": [
    { "role": "user", "content": "I always take the night train to Berlin." },
    { "role": "assistant", "content": "Noted." }
  ]
}
200
{
  "request_id": "23ba77f0c6474ccb8dc5d65d1a44d069",
  "data": {
    "task_id": "b80658f8-c2f4-4e1b-8a98-c2bc42189e02",
    "status": "queued",
    "accepted_messages": 2,
    "idempotent_replay": false,
    "created_at": 1787475991675
  }
}

En søgning returnerer rangordnede træf. Selve erindringen ligger på posten inde i hvert træf, ikke på træffet — og scoren er en sammensat placering snarere end en sikkerhed, så læs indholdet for at bedømme relevans i stedet for at sætte en grænse ved tallet.

POST /api/v2/memory/search
{
  "memory_type": "user",
  "user_id": "[email protected]",
  "query": "how do they prefer to travel",
  "top_k": 5
}
200
{
  "request_id": "9130cb814f654e1ea042497d6362b08d",
  "data": {
    "hits": [
      {
        "record": {
          "id": "a1b2c3",
          "memory_type": "user",
          "subject_id": "[email protected]",
          "session_id": "s_17",
          "category": "preference",
          "content": "Prefers the night train to Berlin.",
          "confidence": 0.82,
          "version": 1,
          "created_at": 1787475991675,
          "updated_at": 1787475991675
        },
        "score": 0.0328,
        "rank": 1,
        "vector_rank": 1,
        "lexical_rank": 1
      }
    ],
    "method": "hybrid"
  }
}

Hvert felt i hvert kald, med dets præcise type, tilladte værdier og standardværdier, udgives som en maskinlæsbar kontrakt. Den genereres ud fra netop de definitioner, serveren validerer imod, så den kan ikke beskrive et felt, serveren ikke håndhæver. Peg en klientgenerator på den.

the complete contract
https://pfmem-api.packagefactory.dk/openapi.json

Hvad der er betroet, og hvad der ikke er

Hver post bærer to svar om tillid, og de handler om forskellige ting. Det ene er, om et menneske har godkendt den. Det andet er, om den når frem til den, der spørger. Et opslag med en API-nøgle får markeringen i sit indhold og antallet i sit svar; et opslag fra en indlogget session ser det hele, mærkat og alt.

Felter om tillid
FeltVærdierBetydning
verificationverifiedunverifiedrejectedOm et menneske har godkendt den. Det kan kun en indlogget person, så en nøgle skriver den ikke-godkendte værdi; den afviste værdi er en persons melding om, at noget er forkert, og den udleveres aldrig — hverken et opslag eller en redigering med en nøgle kan hente den tilbage, kun en person, der redigerer teksten på webstedet. Et atom er kun godkendt, hvis hver samtaletur, det henviser til, også er det.
availabilityservedwithheldquarantinedOm netop denne kalder får posten. Den udleverede værdi når frem; den tilbageholdte gør ikke og oplyses kun som et antal; den isolerede blev taget ud af omløb af en indberetning, så ingen nøgle får den, mens en indlogget session stadig ser den i panelet.
withheld_countet helt talHvor mange poster dette opslag udelod, fordi de er tilbageholdt for denne kalder — talt over hele udvalget og ikke kun over siden. Altid 0 for en session, som selv får dem.
pending_versionet objekt, eller fraværendeVed et opslag i en fremgangsmåde: den nyere version, en nøgle har skrevet, som ingen har godkendt, nævnt når opslaget udleverer den ældre godkendte version. Fraværende når hovedversionen selv er det, der udleveres, hvilket er tilfældet, indtil en version er blevet godkendt.

Markeringen foran ikke-godkendt indhold

[unverified]

Et opslag med en API-nøgle får ikke-godkendt indhold med dette præfiks foran, så en model, der læser det, får at vide, at ingen har godkendt det. Præfikset lægges på svaret og gemmes aldrig: posten beholder sin egen tekst, og et menneske, der læser samme post, ser intet præfiks.

200
{
  "request_id": "9130cb814f654e1ea042497d6362b08d",
  "data": {
    "hits": [
      {
        "record": {
          "id": "a1b2c3",
          "content": "[unverified] Prefers the night train to Berlin.",
          "verification": "unverified",
          "availability": "served"
        },
        "score": 0.0328,
        "rank": 1
      }
    ],
    "method": "hybrid",
    "withheld_count": 2
  }
}

Antallet af det, du ikke fik

En liste, en søgning og en genkaldelse oplyser alle, hvor mange poster de udelod, i stedet for lydløst at svare med færre. Antallet er et faktum om kalderens helt udvalg — emnet, korpusset og credentialen, ikke forespørgslen og ikke de filtre, denne anmodning tilføjede — så det kan ikke indsnævres ved at spørge igen. Ingen tekst, intet id og intet navn fra en tilbageholdt post når svaret.

En fremgangsmåde udleverer den godkendte version, mens en nyere venter

En fremgangsmåde er en måde at arbejde på, så når et menneske først har godkendt en version, udleveres en nyere, som en nøgle skriver, ikke til agenter: opslaget svarer med den godkendte version og nævner den nyere som ventende. Er der endnu ikke godkendt nogen version, udleveres den nyeste med markøren for ikke-godkendt i stedet — en fremgangsmåde, som kun en nøgle har skrevet, kan bruges, og kun en nyere nøgleversion bag en godkendt holdes tilbage.

pending_version

Markeret til gennemgang

Siden under Gennemgang i dashboardet er der, hvor et menneske ser, hvad der blev tilbageholdt, og svarer på det. En godkendelse dér er det eneste i produktet, der gør en post betroet: intet, en nøgle sender, sætter tillidssvaret, og intet, en nøgle sender, gør en post tilgængelig.

Procedurer

En procedure er en fremgangsmåde, dine agenter holder fast i: trinnene i en udgivelse, en vejledning til at håndtere en alarm, den måde dette arbejdsområde rent faktisk håndterer en refusion på. En hukommelse er et faktum, udtrækningen fandt for dig; en procedure er et dokument, du skriver med vilje, og den er versioneret fra det øjeblik, den oprettes.

Procedure-endpoints
EndpointFormål
POST /api/v2/memory/procedures/createSkriv en ny procedure. Den kommer tilbage som version 1.
POST /api/v2/memory/procedures/getLæs én procedure, teksten inklusive — også en, der er taget ud af brug.
POST /api/v2/memory/procedures/updateTilføj en ny version. Alle tidligere versioner forbliver læsbare.
POST /api/v2/memory/procedures/archiveTag en procedure ud af brug. Den forsvinder fra oversigt og søgning, og intet går tabt.
POST /api/v2/memory/procedures/listDe procedurer, denne nøgle kan se, senest ændrede først.
POST /api/v2/memory/procedures/searchFind procedurer på ordlyd, med det matchende afsnit som uddrag.
POST /api/v2/memory/procedures/versionsVersionshistorikken bag den nuværende version, nyeste først.

Hvem kan se en

Synlighed afgør, hvem der kan se en procedure. Privat betyder den agent, der ejer den, plus enhver nøgle, der læser hele arbejdsområdet. Delt betyder alle i det arbejdsområde. Et kald, der ikke nævner nogen af dem, bliver privat, fordi deling er et valg og ikke en standard. Ingen af værdierne rækker uden for det, og intet i et kald kan udvide nogen af dem. Synligheden vælges, når proceduren oprettes, og en opdatering kan flytte den mellem de to.

"visibility": "private""visibility": "team"

En nøgle, der ikke er bundet til en agent, kan ikke oprette en privat procedure — privat betyder privat for én agent, så en sådan nøgle ville gemme noget, den aldrig selv kunne læse igen. Kaldet afvises med en valideringsfejl, der nævner den værdi, du skal bruge i stedet.

POST /api/v2/memory/procedures/create
{
  "name": "nightly-release",
  "description": "how we ship at night",
  "content": "Freeze at six, run the checks, ship only when green.",
  "visibility": "team",
  "reason": "first written down"
}
200
{
  "request_id": "4c7f1d02a1a34a2f9a3f0b1c6d5e8f70",
  "data": {
    "procedure": {
      "procedure_id": "pr_9f3c1a2e-5d47-4b8a-9c31-6e0d2f7b4a15",
      "name": "nightly-release",
      "description": "how we ship at night",
      "kind": "procedure",
      "scope": "workspace",
      "workspaces": null,
      "origin": "agent",
      "agents_can_edit": false,
      "version": 1,
      "status": "active",
      "visibility": "team",
      "owner_agent_id": "release-bot",
      "user_id": null,
      "created_at": 1787475991675,
      "updated_at": 1787475991675,
      "content": "Freeze at six, run the checks, ship only when green.",
      "includes": []
    }
  }
}

Hvem kan ændre en

For de to legitimationer, der kun læser deres egne hukommelser, er denne flade den bredere: en nøgle bundet til én agent læser kun de hukommelser, den selv skrev, men læser sine egne procedurer og alle delte, og en nøgle bundet til én person læser de delte — en vejledning, kun forfatteren kan læse, gavner ingen. Det går den anden vej for de to, der i forvejen læser hver eneste hukommelse i arbejdsområdet, mens de skriver i eget navn: den, der er bundet til en agent, læser de delte procedurer plus dem, den selv har skrevet, den, der er bundet til en person, læser de delte, og ingen af dem når en anden agents private procedure. Enhver legitimation, der ikke er bundet til et subjekt, læser hele arbejdsområdet.

At se en procedure og at skrive hen over den er to forskellige spørgsmål, og skrivningen er den snævreste. En ny version tilføjes, og en procedure tages ud af brug, af det subjekt, der ejer den — den agent, den blev oprettet under, eller den person, der oprettede den, når ingen agent ejer den — eller af en nøgle, der ikke er bundet til noget subjekt, og som derfor svarer for hele arbejdsområdet. En legitimation, der spænder over en hel konto, læser denne flade og skriver ikke på den: at skrive betyder at angive det arbejdsområde, du skriver i, og det gør en arbejdsområdenøgle allerede.

For alle andre svarer proceduren præcis som en, der ikke findes. Det er med vilje: et afslag, der sagde “ikke din”, ville bekræfte, at den er der, så en procedure, du kan læse men ikke ændre, afvises med samme ord som et forkert id. Dens versionshistorik svarer på samme måde.

Versioner, og at tage en ud af brug

En opdatering retter aldrig på stedet. Den tilføjer en ny nuværende version og bevarer alle før den, hver med et stempel om, hvem der skrev den, så en gammel vejledning aldrig går tabt under en ny. Angiv den version, du læste, og tilføjelsen afvises i stedet for at skrive hen over arbejde, du aldrig så. At tage en procedure ud af brug fjerner den fra oversigt og søgning, mens den nuværende tekst og hele historikken forbliver læsbare for enhver, der har id'et, og intet på denne flade sletter. At tage en ud af brug er en vej uden retur: en procedure, der er taget ud af brug, får ingen flere versioner, og intet henter den tilbage, så en fremgangsmåde, der ændrer sig bagefter, er en ny procedure med et nyt id.

POST /api/v2/memory/procedures/update
{
  "procedure_id": "pr_9f3c1a2e-5d47-4b8a-9c31-6e0d2f7b4a15",
  "content": "Freeze at seven now.",
  "expected_version": 1,
  "reason": "the freeze moved an hour"
}

At finde en

Søgning og oversigt svarer med sammendrag — navnet, beskrivelsen, den nuværende version, dens tilstand, dens synlighed og dens ejer — og søgningen tilføjer det afsnit, der matchede, med de matchende ord markeret, så fjern markeringen eller escape teksten, før du viser den. En søgning læser navnet, beskrivelsen og begyndelsen af indholdet, så en præcis beskrivelse er det, der gør en lang procedure mulig at finde. Selve teksten kommer tilbage fra læsningen og fra hver skrivning. En søgning her er en fremsøgning og tæller mod den samme kvote som en hukommelsessøgning.

POST /api/v2/memory/procedures/search
{
  "query": "release freeze",
  "top_k": 5
}
200
{
  "request_id": "b0f9a71c5e2d4d15b7a0c9e3f4218ad6",
  "data": {
    "hits": [
      {
        "procedure": {
          "procedure_id": "pr_9f3c1a2e-5d47-4b8a-9c31-6e0d2f7b4a15",
          "name": "nightly-release",
          "description": "how we ship at night",
          "version": 2,
          "status": "active",
          "visibility": "team",
          "owner_agent_id": "release-bot",
          "user_id": null,
          "created_at": 1787475991675,
          "updated_at": 1787648791675
        },
        "score": 0.41,
        "excerpt": "<mark>Freeze</mark> at seven now."
      }
    ]
  }
}

En eksport af et arbejdsområde indeholder dem: hver procedure og hver version af hver procedure.

Opgaver

De eneste to GET-kald i hukommelses-API'et. Statusserne er queued, running, succeeded, failed og cancelled; de tre sidste er endelige, så hold op med at spørge, når du når en af dem.

Opgaveendpoints
EndpointFormål
GET /api/v2/tasksViser baggrundsopgaver.
GET /api/v2/tasks/{task_id}Én opgaves status og fremdrift.

Administration

Kun med master-nøgle. Det er her, arbejdsområder og nøgler styres, og det ligger bevidst uden for kommandolinjeklientens flade.

Administrationsendpoints
EndpointFormål
POST /api/v2/admin/tenantsOpretter et arbejdsområde.
POST /api/v2/admin/tenants/listViser kontoens arbejdsområder.
POST /api/v2/admin/tenants/suspendSuspenderer et arbejdsområde. Kan gøres om.
POST /api/v2/admin/tenants/resumeGenoptager et suspenderet arbejdsområde.
POST /api/v2/admin/tenants/eraseSletter et arbejdsområde. Uigenkaldeligt — alt i det fjernes helt.
POST /api/v2/admin/tenants/exportEksportér alt, hvad der er gemt for ét arbejdsområde, i ét dokument.
POST /api/v2/admin/tenants/embedding-versionFlyt et arbejdsområde til en anden indlejringsversion. Genindlejringen kører som en opgave.
POST /api/v2/admin/embedding-versions/listList de registrerede indlejringsversioner, et arbejdsområde kan bruge.
POST /api/v2/admin/audit/listLæs kontoens revisionsspor: nøgler, arbejdsområder, legitimationsoplysninger og planændringer.
POST /api/v2/admin/keysUdsteder en nøgle.
POST /api/v2/admin/keys/listViser nøgler. Returnerer aldrig en hemmelighed.
POST /api/v2/admin/keys/revokeTilbagekalder en nøgle.
POST /api/v2/admin/keys/rotateRoterer en nøgle og udsteder dens afløser.
POST /api/v2/admin/credentialsGemmer din egen udbydernøgle, krypteret.

Udgivelseskanalen

Fem offentlige ruter uden autentificering, der leverer installationsprogrammet og de offentliggjorte artefakter. De er bevidst fraværende i OpenAPI-dokumentet: det dokument er den hukommelseskontrakt, din applikation kalder, og et shell-script og en download er infrastruktur.

Offentlige udgivelsesendpoints
EndpointReturnerer
GET /install.shInstallationsprogrammet, stemplet med det origin, det blev hentet fra.
GET /cli/latestDen offentliggjorte version, dens sha256 og dens størrelse.
GET /cli/download/:versionKlientbundtet.
GET /cli/skill/latestDen offentliggjorte skill-version, dens sha256 og dens størrelse.
GET /cli/skill/download/:versionSelve skill'en.

Konventioner, det er værd at kende, før du skriver en klient

Næsten alt er POST.
Også læsninger. En læsning tager en body med filtre, og en nøgle hører hjemme i en header frem for i en URL, som proxyer og browserhistorik registrerer. De to task-endpoints er de eneste GET-kald. Behandl det ikke som en forglemmelse, der skal rettes.
Tidsstempler er unix-millisekunder.
Tretten cifre, mindst 1000000000000, i begge retninger. En værdi i sekunders præcision afvises frem for at blive læst som en dato i 1970.
En læsning navngiver højst ét subjekt.
Visningen og søgningen tager hver ét subjekt-id, og det skal svare til hukommelsestypen: en forespørgsel på user navngiver et user_id, en forespørgsel på agent navngiver et agent_id. Det er tilladt slet ikke at nævne noget, og det betyder alle subjekter af den type, nøglen i forvejen kan nå. At sende begge er den ene kombination, der fejler valideringen, så byg valget som en kontakt med en alle-position frem for to felter. En skrivning er strengere: at gemme en hukommelse navngiver præcis ét subjekt, for den skal tilhøre nogen.
Bodies valideres strengt.
Et ukendt felt er en valideringsfejl, ikke noget, der stille ignoreres. Et stavet forkert navn fejler højlydt frem for at se ud til at virke — og intet felt, du kunne sende, navngiver overhovedet et arbejdsområde, et filter eller en embedding-version.