Embed Widget
Indlejr dine udgivne apps på eksterne hjemmesider ved hjælp af embed-widget funktionen.
Oversigt
Embed-widget giver dig mulighed for at integrere dine AgentBase-apps direkte på andre hjemmesider. Brugere kan interagere med appen uden at forlade din hjemmeside.

Adgang
- Udvikler+: Kan konfigurere og administrere embed-widgets
- Kun udgivne apps: Fanen Widget står altid på app-detaljesiden, men indholdet er låst, indtil appen er udgivet. Er den ikke det, møder du kortet Widget kræver en udgivet app med teksten "Widget-konfiguration og embed-tokens bliver tilgængelige, når du udgiver appen"
Embed Tokens
For at bruge embed-widget på eksterne hjemmesider, skal du oprette et embed-token. Tokenet bruges til at autentificere dine embed-widgets.

Opret Token
- Åbn app-detaljesiden for en udgivet app
- Gå til fanen Widget (fanen er der altid, men indholdet låses op, når appen er udgivet)
- Klik på "Opret token"
- Angiv et beskrivende navn for tokenet
- (Valgfrit) Tilføj tilladte domæner for ekstra sikkerhed

Rediger tilladte domæner
Domænelisten kan ændres, efter tokenet er oprettet — klik på klode-ikonet i
token-tabellen. Ét domæne per linje, med http:// eller https:// og uden sti:
https://esdh.kommune.dk
https://*.kommune.dk
https://*.kommune.dk matcher underdomæner (esdh.kommune.dk, a.b.kommune.dk), men ikke kommune.dk selv. Et tomt felt
tillader alle domæner.
Du skal ikke oprette et nyt token, når widget'en flytter til et nyt domæne — så holder de sider, der allerede bruger tokenet, op med at virke.
Token Sikkerhed
- Tilladte domæner: Begræns hvilke domæner der kan bruge tokenet
- Rate limiting: Beskyt mod misbrug med automatisk hastighedsbegrænsning
- Tilbagekald: Du kan til enhver tid deaktivere et token
Gem tokenet et sikkert sted! Det vises kun én gang ved oprettelse.
Layout Indstillinger
Valgene i fanen Widget — layout, tema, stil og indholdsindstillinger — gemmes ikke på appen. De lever kun i browseren, så længe du har fanen åben, og skrives ind i den kode, du genererer nederst på siden. Genindlæser du siden, står felterne på standardværdierne igen. Det er altså den kopierede kode, du skal gemme — ikke opsætningen. Kun dine embed-tokens gemmes.
Vælg hvordan din widget skal vises på hjemmesiden.

Vertikal Layout
Standard layout med inputs stablet lodret. Bedst til formularer med mange felter.

Horisontal Layout
Inputs vises side om side. Velegnet til kompakte formularer med få felter.

Kompakt Layout
Minimalistisk visning med reduceret afstand. Perfekt til sidebar-widgets.

Tema Tilpasning
Som med layout gemmes temaet ikke på appen — se noten under Layout Indstillinger.
Farvetema
Vælg mellem lys, mørk eller automatisk tema.
Lys tilstand:

Mørk tilstand:

Auto tilstand: Automatisk tilpasning baseret på brugerens systemindstillinger.
Primær Farve
Vælg en primær farve fra foruddefinerede presets eller brug en brugerdefineret farve.

Foruddefinerede farver inkluderer:
- Coral (#e86c4a, standard)
- Terracotta
- Ocean
- Indigo
- Violet
- Emerald
- Teal
- Amber
- Orange
- Rose
Stil Indstillinger
Tilpas udseendet af din widget med avancerede stil-indstillinger.

Skrifttype
Vælg mellem forskellige skrifttyper:
- System (standard)
- Sans-serif
- Serif
- Monospace
Hjørner (Border Radius)

Juster hjørnernes afrunding:
- Skarpe: Skarpe hjørner
- Lille: Let afrunding
- Medium: Standard afrunding
- Stor: Markant afrunding
- Runde: Maksimal afrunding
Input Stil

Vælg mellem:
- Kant: Standard ramme omkring input
- Fyldt: Udfyldt baggrund
- Linje: Kun streg under input
Knap Stil

Tilpas kørselsknappen:
- Fyldt: Standard knap
- Kant: Kun ramme
- Ghost: Gennemsigtig baggrund
Skygge

Tilføj dybde med skyggeeffekter:
- Ingen: Ingen skygge
- Subtil: Subtil skygge
- Medium: Standard skygge
- Dramatisk: Markant skygge
Afstand (Spacing)

Juster den interne afstand:
- Kompakt: Minimalt mellemrum
- Normal: Standard mellemrum
- Afslappet: Ekstra mellemrum
Live Forhåndsvisning
Se dine ændringer i realtid med den integrerede forhåndsvisning.

Lys forhåndsvisning:

Mørk forhåndsvisning:

Indholdsindstillinger
Tilpas hvilke elementer der vises i widgetten:
- Vis beskrivelse: Vis app-beskrivelsen
- Vis brugervejledning: Vis hjælpetekst
- Vis branding: Vis "Bygget med AgentBase"
- Tekstjustering: Venstre, center eller højre
Inputfelter
Widget'en tegner de felter, appen udstiller — tekst, tal (med appens grænser), afkrydsning, dropdown (også afhængige valg), lister, filupload og lyd.
Ét felt kan widget'en ikke udfylde: et valg blandt AgentBase-enheder (fx et dokument fra biblioteket), som kræver en bruger, der er logget ind. Er et sådant felt påkrævet, viser widget'en i stedet for kørselsknappen en besked om, at appen ikke kan køres herfra — skjul feltet, eller giv det en standardværdi under appens opsætning.
Fil
Inputs af filtypen får en filvælger. Appens egne begrænsninger følger med:
accept styrer hvilke filtyper vælgeren tilbyder, og en fil over
størrelsesgrænsen afvises med en besked i stedet for at blive sendt afsted.
Inputs, der tager en liste af filer, kan vælge flere ad gangen.
Lyd
Lydinputs (fx til transskribering) har to faneblade: Upload og Optag.
Optagelsen bruger browserens mikrofon og kræver, at siden serveres over
https:// — ellers giver browseren ikke adgang, og widget'en siger det.
Brugeren kan afspille optagelsen, før kørslen startes.
Generér Embed Kode
Når du har konfigureret din widget, kan du generere koden til indlejring.
Både HTML- og React-koden indsætter kun tokenets første tegn efterfulgt af ... — for
eksempel token: 'emb_ab12...'. Widget'en virker først, når du selv erstatter
pladsholderen med den fulde token. Det er den token, du fik vist én gang, da du oprettede
den (se advarslen under Token Sikkerhed ovenfor); har du ikke gemt den, skal du oprette
et nyt token.
Har appen mere end ét token, dukker en Token-vælger op øverst i afsnittet, så du kan vælge hvilket token koden skal skrives til. Har du kun ét token, bruges det automatisk.
HTML Kode
Kopier HTML-koden og indsæt den på din hjemmeside:
<!-- AgentBase Embed Widget -->
<div id="agentbase-widget"></div>
<script src="https://<din-agentbase-host>/embed.js"></script>
<script>
AgentBase.mount('#agentbase-widget', {
appId: 'DIN_APP_ID',
token: 'DIT_EMBED_TOKEN',
layout: 'vertical',
theme: {
mode: 'light',
primaryColor: '#e86c4a',
borderRadius: 'md',
inputStyle: 'outline',
buttonStyle: 'solid',
fontFamily: 'system',
shadow: 'sm',
spacing: 'normal',
showBranding: true,
showDescription: true,
showUserManual: true,
textAlign: 'left'
}
});
</script>
embed.js serveres fra samme domæne som din AgentBase-app — erstat <din-agentbase-host> med det domæne, hvor din app kører. Den genererede kode i "Widget"-fanen indsætter automatisk den korrekte host.
Widget'en kalder AgentBase' API på https://api.agentbase.dk som standard. Kører
du AgentBase på egne servere, skal du pege den derhen med apiBaseUrl — bemærk
at det er API'ets adresse, ikke den host embed.js hentes fra:
AgentBase.mount('#agentbase-widget', {
appId: 'DIN_APP_ID',
token: 'DIT_EMBED_TOKEN',
apiBaseUrl: 'https://api.min-installation.dk/api/v1',
});
React Kode
For React-projekter monterer du widget'en med AgentBase.mount i en useEffect og rydder op med destroy. Der er ingen npm-pakke — SDK'et indlæses via embed.js-scriptet:
import { useEffect, useRef } from 'react';
// Tilføj SDK-scriptet til din HTML, eller indlæs det dynamisk
// <script src="https://<din-agentbase-host>/embed.js"></script>
function AgentBaseWidget() {
const containerRef = useRef(null);
const widgetRef = useRef(null);
useEffect(() => {
if (containerRef.current && window.AgentBase) {
widgetRef.current = AgentBase.mount(containerRef.current, {
appId: 'DIN_APP_ID',
token: 'DIT_EMBED_TOKEN',
layout: 'vertical',
theme: {
"mode": "light",
"primaryColor": "#e86c4a",
"borderRadius": "md",
"inputStyle": "outline",
"buttonStyle": "solid",
"fontFamily": "system",
"shadow": "sm",
"spacing": "normal",
"showBranding": true,
"showDescription": true,
"showUserManual": true,
"textAlign": "left"
},
onExecutionComplete: (results) => {
console.log('Kørsel færdig:', results);
}
});
}
return () => {
widgetRef.current?.destroy();
};
}, []);
return <div ref={containerRef} />;
}
Flere indstillinger i koden
Ud over layout og tema tager AgentBase.mount() en række indstillinger, som ikke findes i
fanen Widget — du skriver dem selv ind i koden.
| Indstilling | Betydning |
|---|---|
fieldOrder | Rækkefølgen af felterne, angivet med feltnavne. Felter, der ikke står på listen, lægges til sidst. |
submitButtonText | Din egen tekst på kørselsknappen. Bemærk: den erstatter både teksten "Kør" og teksten "Kører…", der ellers vises under kørslen. |
resetButtonText | Din egen tekst på Nulstil-knappen. En tom tekst ('') skjuler knappen helt. |
showProgress | Sæt til false for at skjule statuslinjen under kørslen. |
showLabels | Sæt til false for at skjule felternes ledetekster. |
Widget'en kan også give din side besked undervejs:
| Tilbagekald | Kaldes når |
|---|---|
onExecutionStart | Kørslen går i gang |
onExecutionProgress | Der er nyt om fremdriften |
onExecutionComplete | Kørslen er færdig (får resultaterne) |
onExecutionError | Kørslen fejler (får fejlbeskeden) |
onInputChange | Brugeren ændrer et felt (får feltnavn og værdi) |
AgentBase.mount() giver dig samtidig et håndtag til widget'en, så du kan styre den fra din
egen side:
const widget = AgentBase.mount('#agentbase-widget', { /* ... */ });
widget.setInput('navn', 'Anders'); // udfyld et felt
widget.getInputs(); // læs de aktuelle værdier
widget.execute(); // start kørslen
widget.reset(); // ryd formularen
widget.destroy(); // fjern widget'en fra siden
widget.isExecuting; // kører den lige nu?
widget.lastResults; // resultatet af den seneste kørsel
Widget'en honorerer også temaindstillingerne backgroundColor (baggrundsfarve) og
textColor (tekstfarve), men opsætningssiden tilbyder dem ikke — du skal skrive dem ind i
theme-blokken i koden selv.
Kald appen uden widget'en
Bygger du din egen brugerflade, kan du kalde appen direkte fra browseren med den samme
embed-token. Tokenen sendes som ?token=emb_… eller i headeren
Authorization: Bearer emb_…, og de tilladte domæner gælder præcis som for widget'en.
| Kald | Bruges til |
|---|---|
GET /api/v1/embed/{app_id}/schema | Appens felter og outputs |
POST /api/v1/embed/{app_id}/run | Kør og vent på svaret |
POST /api/v1/embed/{app_id}/run-stream | Kør og følg fremdriften (server-sent events) |
POST /api/v1/embed/{app_id}/run-async | Start en kørsel og få et kørsels-id med det samme |
GET /api/v1/embed/{app_id}/runs/{execution_id} | Spørg til en kørsel startet med run-async |
Body til de tre kørselskald er {"inputs": {"feltnavn": "værdi"}}.
Lange kørsler: start asynkront
En kørsel, der tager minutter, overlever sjældent et almindeligt kald — en proxy, en
load balancer eller browseren selv giver op først, og så ved du ikke engang, om kørslen
nåede at gå i gang. Start den i stedet med run-async:
const base = 'https://api.agentbase.dk/api/v1/embed/' + appId;
const headers = { Authorization: 'Bearer ' + embedToken, 'Content-Type': 'application/json' };
const accepted = await fetch(base + '/run-async', {
method: 'POST',
headers,
body: JSON.stringify({ inputs: { tekst: 'Hej' } }),
});
const { execution_id } = await accepted.json(); // 202 Accepted
let run;
do {
await new Promise((r) => setTimeout(r, 3000));
run = await (await fetch(base + '/runs/' + execution_id, { headers })).json();
} while (run.status === 'PENDING' || run.status === 'RUNNING');
if (run.status === 'COMPLETED') console.log(run.results);
else console.error(run.error);
run-asyncafviser det samme somrun(manglende eller tilbagekaldt token, domæne uden adgang, app der ikke er udgivet eller er deaktiveret, for mange kald), og det sker med det samme. Et202betyder derfor, at kørslen er startet. Et forkert udfyldt felt bliver til en kørsel med statusFAILEDog samme forklaring, somrunville have svaret med.resultser præcis det samme, somrunville have svaret — også filer.- Kørslen kan kun hentes med den token, der startede den. En anden token, også til
samme app, får
404. - Tager du appen offline, kan en kørsel, der allerede er startet, stadig hentes. Tilbagekalder du tokenen, kan den ikke.
- Spørg højst hvert 2.–5. sekund. Spørgsmålene tæller i deres egen pulje med tokenens
grænse pr. minut, så de bruger ikke af de kald, du skal bruge til at starte kørsler.
Rammer du grænsen, svarer døren
429med headerenRetry-After, som også kan læses fra en anden side end AgentBase.
Bedste Praksis
Sikkerhed
- Brug domænebegrænsninger: Angiv altid tilladte domæner for dine tokens
- Roter tokens regelmæssigt: Opret nye tokens periodisk
- Overvåg brug: Hold øje med API-forbruget
Brugeroplevelse
- Match dit tema: Tilpas farver til din hjemmesides design
- Test på mobile: Verificer at widgetten fungerer på alle skærmstørrelser
- Klar feedback: Brug loading-indikatorer og fejlmeddelelser
Performance
- Lazy loading: Indlæs kun widgetten når den er synlig
- Caching: Brug browser-caching til hurtigere indlæsning
- Minimér data: Send kun nødvendige felter
Fejlfinding
"Domænet har ikke adgang"
Domænet, siden serveres fra, står ikke på tokenets liste over tilladte domæner.
Beskeden nævner det afviste domæne — kopiér det ind under "Rediger tilladte
domæner" ovenfor. Bemærk at et domæne skal skrives med skema (https://) og
uden sti, og at https:// og http:// tæller som hver sit domæne.
Åbner du testsiden som en lokal fil (file://), sender browseren ingen
Origin-header, og widget'en kan ikke kontrollere domænet. Læg siden på en rigtig
webserver — også en lokal én.
"Peger apiBaseUrl på AgentBase' API?"
apiBaseUrl peger på en webserver i stedet for API'et, og svaret er en
HTML-side. Standarden er https://api.agentbase.dk/api/v1; app-domænet
(agentbase.dk) er ikke API'et.
Widget indlæses ikke
- Tjek at tokenet er gyldigt og ikke tilbagekaldt
- Verificer at domænet er på listen over tilladte domæner
- Tjek at appen er udgivet og aktiv
- Tjek browser-konsollen for fejlmeddelelser
Stilarter ser forkerte ud
- Tjek for CSS-konflikter med din hjemmeside
- Brug mere specifik CSS hvis nødvendigt
- Overvej at bruge iframe-isolation
Kørsel fejler
- Tjek at appen er udgivet og aktiv
- Verificer at alle påkrævede inputs er udfyldt
- Tjek API-kvoter og rate limits