---
title: "Agenttrinn og overføringer"
description: "Del en agent inn i trinn med egne instruksjoner, verktøy og innsamlede verdier, og overfør samtaler mellom agenter midt i samtalen."
---

En enkelt ledetekst gir modellen hele oppgaven på én gang. **Trinn** gir den én
fase av samtalen om gangen: hvert trinn har sine egne instruksjoner, sine egne verktøy,
en valgfri linje som sies ordrett, og verdier den må samle inn før den går
videre. **Overleveringer** lar en annen agent i organisasjonen din overta midt i samtalen,
med transkripsjonen intakt, slik at innringeren aldri trenger å gjenta seg selv.

Hver agent starter som én enkelt ledetekst. Ingenting ved den endres før du legger til
trinn eller overleveringer.

## Trinn eller én enkelt ledetekst?

| Bruk trinn når | Behold én enkelt ledetekst når |
| --- | --- |
| Samtalen har faser som må skje i rekkefølge: verifiser, deretter bestill. | Samtalen er åpen: vanlige spørsmål, resepsjon, generell støtte. |
| En verdi må hentes inn før agenten går videre. | Ingenting må samles inn i en fast rekkefølge. |
| En regel aldri må fravikes, for eksempel «innringere under 18 år går til en verge». | Modellens vurdering er god nok for alle forgreninger. |
| Et oppslag må kjøres på et fast punkt i samtalen. | Verktøy kan kalles når innringeren ber om det. |
| En del av samtalen tilhører en annen agent, med sin egen ledetekst og stemme. | Én persona håndterer alt. |

Trinn er ikke et skriptet telefonmenytre. I et trinn håndterer modellen
samtalen slik den gjør med én enkelt ledetekst. Trinnet avgjør hva den
arbeider med, hvilke verktøy den kan bruke, og hva den trenger før den kan gå videre.

## Slik bygges en agent med trinn

Når en agent har trinn, inneholder `prompt` de **felles instruksjonene**:
personaen og reglene som gjelder i hvert trinn. Hvert trinn legger til sine egne
instruksjoner på toppen. I hver tur ser modellen de felles instruksjonene, navnet
og instruksjonene til det gjeldende trinnet, og verdiene som er samlet inn så langt.

I byggeren bytter du agenten fra **En enkelt ledetekst** til **Trinn**. Du får et
kort per trinn med navn, instruksjoner, si-linje, verktøy, innsamlede verdier
og overganger, en velger for overleveringer og en skrivebeskyttet flytgraf over trinnene.
Når du bytter tilbake til én enkelt ledetekst, tilbys du en flatet ledetekst som slår sammen
de felles instruksjonene og alle trinnene.

Over API-et er `steps` og `handoffs` felt på
[agenten](/api-reference/agents). Som alle agentfelt mellomlagrer en `PATCH` dem
i utkastet; `POST /v1/agents/{agent_id}/deploy` gjør dem aktive. Å sende
`"steps": null` bytter agenten tilbake til én enkelt ledetekst. Testsamtaler og
**Snakk** kjører utkastet.

<Tip>
  [Copiloten](/nb/guides/ask-the-copilot) kan bygge trinn fra en beskrivelse
  («legg til et trinn som verifiserer fødselsdato før bestilling») og redigere ett trinn
  uten å påvirke de andre.
</Tip>

### Trinnfelt

| Felt | Betydning |
| --- | --- |
| `id` | Påkrevd. Små bokstaver, sifre og understreker, starter med en bokstav, opptil 40 tegn. Unik innenfor agenten. |
| `name` | Påkrevd visningsnavn, 1 til 80 tegn. |
| `instructions` | Påkrevd, opptil 20 000 tegn. Støtter `{{var}}`-[samtalevariabler](/nb/guides/call-variables), som `prompt`. |
| `say` | Valgfri linje som sies ordrett når trinnet åpnes, opptil 1 000 tegn. Støtter `{{var}}`. |
| `tools` | `null` gir trinnet tilgang til alle verktøy som er knyttet til agenten. En liste begrenser trinnet til disse verktøyene, etter navn. Innebygde handlinger som `end_call` og `transfer_call` følger agentens innstillinger i hvert trinn. |
| `collect` | Opptil 20 verdier som trinnet samler inn. Hver har et `name`, en `type`, en `description` og `required` (standard er `true`). |
| `on_enter_tool` | Valgfritt verktøynavn som kalles automatisk når trinnet åpnes. Se [Webhook-trinn](#webhook-steps). |
| `transitions` | Sortert liste over hvor trinnet kan gå videre. Se [Overganger](#transitions). |
| `global_when` | Valgfritt. Gjør trinnet tilgjengelig fra ethvert trinn. Se [Globale trinn](#global-steps). |
| `voice` | Valgfri stemme-ID for dette trinnet. Ignoreres når agenten bruker en egendefinert stemmekonfigurasjon. |

Selve grafen er `{"start_step": "<step id>", "steps": [...]}`. Samtalen
starter i `start_step`.

## Overganger

Hver overgang har `to`, en trinn-ID, og nøyaktig én av disse:

- **`when`**: vanlig språk, og **modellen avgjør**. Agenten får et
  innebygd `go_to_step`-verktøy som viser trinnene den kan gå til, med hver
  `when` som begrunnelse for å velge det.
- **`condition`**: en regel for innsamlede verdier, og **koden avgjør**.
  Modellen kan ikke hoppe over den eller snakke seg rundt den.
- **`"always": true`**: gå videre uten kontroll. Koden avgjør først: så snart
  et trinn åpnes, eller når de påkrevde verdiene er samlet inn, vinner den første
  samsvarende `condition`- eller `always`-overgangen før modellen kan velge en
  `when`. Plasser derfor `always` etter betingelsene som reserve, eller alene
  for å koble et trinn direkte til det neste. Et trinn med `always` venter aldri
  på et `when`-valg.

En `condition` er `{"value": <collected name or dotted path>, "op": <op>, "target": <literal>}`:

| `op` | Sann når verdien |
| --- | --- |
| `eq`, `ne` | er lik, eller ikke er lik, `target` |
| `lt`, `lte`, `gt`, `gte` | er mindre enn, høyst, større enn eller minst `target` |
| `in`, `not_in` | er, eller ikke er, én av verdiene i `target`-listen |
| `exists`, `missing` | er, eller ikke er, samlet inn (ingen `target`) |

`eq`, `ne`, `in` og `not_in` sammenligner tekst uten å ta hensyn til store og
små bokstaver etter at mellomrom er fjernet. Tall sammenlignes som tall og datoer
som `YYYY-MM-DD`-strenger. En verdi som aldri ble samlet inn, gjør alle
operatører usanne bortsett fra `missing`.

Skriv `when` og `global_when` som en betingelse, for eksempel «Innringeren vil
bestille en time», ikke som noe som skal sies. Agenten ser dem som interne
rutenotater og blir bedt om aldri å lese dem opp eller nevne at den bytter
trinn.

Når modellen kaller `go_to_step`:

1. Hver `required`-verdi i trinnet må være til stede. Hvis én mangler, får
   modellen vite hvilken, og ber innringeren om den.
2. Verdiene lagres.
3. `condition`- og `always`-overganger kontrolleres i rekkefølge. Den første
   matchen vinner.
4. Ellers flytter agenten til trinnet modellen valgte.
5. Hvis ingenting matcher og modellen ikke oppga noe trinn, blir agenten værende
   der den er.

Et hopp til et [globalt trinn](#global-steps) er unntaket: Innringeren har byttet
tema, så hoppet gjennomføres selv om det fortsatt mangler påkrevde verdier i det
gjeldende trinnet, og før betingelsene i det trinnet kontrolleres.

`condition`- og `always`-overganger kontrolleres også hver gang et trinn åpnes,
så en rekke kodeavgjorte trinn kjøres i én operasjon. Kjeden stopper:

- ved et trinn den allerede har besøkt i denne kjøringen;
- etter 8 hopp;
- ved et trinn som fortsatt har påkrevde verdier å samle inn, med mindre trinnet
  har et `on_enter_tool` (et webhook-trinn ruter alltid basert på resultatet).

Bare `say`-linjen i trinnet der kjeden stopper, blir sagt.

Et trinn uten overganger er **endelig**. Agenten avslutter der og avslutter
eller videresender samtalen med de vanlige innebygde handlingene sine.

## Samle inn verdier

List opp hva et trinn trenger i `collect`. Modellen sender verdiene når den
kaller `go_to_step`, og de forblir tilgjengelige resten av samtalen.

| `type` | Inneholder |
| --- | --- |
| `string` | Vilkårlig tekst |
| `number` | Et tall |
| `boolean` | `true` eller `false` |
| `date` | En dato som `YYYY-MM-DD` |

Innsamlede verdier er samtaleinnhold. De vises på samtalen ved siden av
transkripsjonen og følger de samme reglene for oppbevaring, sletting og
sladding. Når samtaleopptak for agenten er slått av, lagres eller sendes
innsamlede verdier verken i webhooks; trinntidslinjen er fortsatt tilgjengelig.
Se [Hvor du ser det i en samtale](#where-to-see-it-on-a-call).

## Si-linjer

`say` uttales nøyaktig slik den er skrevet når agenten går inn i trinnet. Modellen fortsetter deretter i det nye trinnet i samme svar, med kjennskap til at linjen nettopp ble sagt, slik at den ikke gjentar den. Bruk `say` for hilsener, påkrevde opplysninger og fast ordlyd, og la modellen håndtere resten av svaret.

Starttrinnets `say` er agentens åpningslinje når den snakker først, etter en eventuell samtykkemelding. Når innringeren snakker først, åpner den agentens første svar til en person, aldri til en IVR eller en talemeldingshilsen.

Et trinns `say` uttales ikke på nytt når samtalen returnerer til det via
`__previous__` eller en tilbakelevering. Skriv den slik den skal høres ut: skriv ut alt stemmen kan feiltolke. Si-linjer støtter anropsvariablene `{{var}}`, men ikke innsamlede verdier.

## Webhook-trinn

Sett `on_enter_tool` til ett av agentens verktøy, så kjører det så snart trinnet åpnes, uten å vente på modellen. Argumentene er de innsamlede verdiene hvis navn samsvarer med verktøyets parameternavn. Resultatet lagres som en innsamlet verdi med navnet `<tool>_result`, avkortet til 4 KB, og trinnets `condition`- og `always`-overganger kontrolleres umiddelbart, slik at oppslaget kan rute samtalen basert på sitt eget resultat.

Den lagrede verdien har to felt:

| Felt | Inneholder |
| --- | --- |
| `status` | HTTP-statuskoden endepunktet ditt returnerte. |
| `response` | Svarteksten. |

Rut på et felt i svarteksten med `lookup_account_result.response.<field>`, og på
statuskoden med `lookup_account_result.status`.

Oppslaget kjører i opptil 8 sekunder, eller verktøyets egen tidsavbruddsgrense hvis den er kortere. Hvis det tar mer enn 3 sekunder, sier agenten en kort linje slik at innringeren ikke blir stående i stillhet. Hvis endepunktet ditt returnerer en statuskode på 400 eller høyere, eller ikke svarer i tide, forteller agenten innringeren at den ikke kunne sjekke det akkurat nå, og fortsetter med det den kan gjøre.

## Globale trinn

Et trinn med `global_when` kan nås fra ethvert trinn når denne beskrivelsen stemmer. Modellen avgjør dette, på samme måte som med `when`. Bruk det for temaer en innringer kan ta opp når som helst: fakturaspørsmål, et ønske om å snakke med et menneske, en klage.

En overgang med `"to": "__previous__"` i et globalt trinn returnerer samtalen til trinnet som var aktivt før det, slik at innringeren fortsetter der de slapp. Trinnet gjenopptas: `on_enter_tool` kjører ikke igjen, `say` gjentas ikke, og agenten fortsetter uten å starte på nytt.

## Overføringer

`handoffs` viser andre agenter i organisasjonen din som kan overta anropet:

```json
[{"agent_id": 413, "when": "The caller asks about billing or a refund"}]
```

Agenten får et innebygd `hand_off`-verktøy med disse agentene og årsakene. Som
med overganger er hver `when` et internt rutingnotat og blir aldri lest opp.

Når den overfører, sier agenten én kort setning som forteller innringeren hvor
de blir sendt, for eksempel «Klart, jeg setter deg over til faktureringsteamet vårt», med sin egen
stemme. Deretter overtar mål-agentens prompt, trinn, verktøy og stemme, og
anropet fortsetter med samme transkripsjon. Den nye agenten presenterer seg
kort og svarer på innringerens siste forespørsel; den kunngjør ikke en
overføring. Mål-agentens kunnskapsbase er tilgjengelig fra da av.

Første gang et anrop når en agent, starter det i agentens `start_step`:
trinnets `on_enter_tool` kjøres, og `say` blir sagt. Når anropet overføres
tilbake til en agent det allerede har vært hos, fortsetter agenten i trinnet
den var på, uten å kjøre `on_enter_tool`, gjenta `say` eller presentere seg
igjen. Innsamlede verdier deles av alle agentene i anropet.

- En mål-agent må være en agent i samme organisasjon, og en agent kan ikke
  overføre til seg selv.
- Alt på anropsnivå blir hos agenten som svarte: produkt, språk, hvem som
  snakker først, talepost, samtykkevarsel og alle andre anropsinnstillinger.
- Mål-agenter kan overføre videre og tilbake. Ett anrop kan nå opptil 8 agenter.
- Et testanrop kjører utkastet til agenten du tester. Agentene den overfører til,
  kjører de publiserte versjonene sine.
- Hvis to agenter har et verktøy med samme navn og ulike definisjoner, beholdes
  bare ett for anropet, og verktøyet til agenten som svarte, vinner alltid.
  Byggeren advarer deg når du lagrer.
- En agent kan ha overføringer uten trinn. Hele prompten brukes som den er.

`go_to_step` og `hand_off` er reservert for agenter med trinn eller overføringer,
så dine egne verktøy kan ikke bruke disse navnene.

## Hvor du ser det i et anrop

Åpne anropet i **Anropshistorikk**. En tidslinje for trinn ved siden av
transkripsjonen viser hvert trinn anropet gikk inn i og hvorfor, og de
innsamlede verdiene vises sammen med den.

[Anropsobjektet](/api-reference/calls#retrieve-a-call) og webhooken for fullført
anrop ([`telephony.complete` / `web.complete`](/nb/webhooks/call-complete)) inneholder
de samme dataene som `steps_trace` og `collected_values`. Begge mangler i anrop
uten trinn.

```json
"steps_trace": [
  {"t_ms": 0, "agent": "a412", "step": "greet", "via": "start"},
  {"t_ms": 51230, "agent": "a412", "step": "verify", "via": "model"},
  {"t_ms": 98410, "agent": "a412", "step": "minor", "via": "condition"}
],
"collected_values": {"full_name": "Dana Reyes", "dob": "2010-04-02", "age": 15}
```

`agent` er `a` etterfulgt av agent-ID-en. `via` angir hva som flyttet anropet:

| `via` | Betydning |
| --- | --- |
| `start` | Anropet startet i dette trinnet. |
| `model` | Modellen valgte trinnet via `go_to_step`, en `when` eller en `global_when`. |
| `condition` | En `condition`- eller `always`-overgang samsvarte. |
| `on_enter` | En overgang samsvarte med resultatet fra et webhook-trinn. |
| `handoff` | En annen agent overtok. |

## Hvor trinn kjører

Trinn kjører direkte på **Spark**, **Bolt** og alle **Storm**-produkter, for
inngående, utgående og kampanjeanrop, testanrop og nett- og widgetanrop.

Overalt ellers fungerer agenten fortsatt, bare uten strukturen: den kjører en
flat prompt som slår sammen de delte instruksjonene og hvert trinn, i rekkefølge.
Dette omfatter:

- de eksperimentelle Bolt-produktene;
- [Realtime](/nb/guides/use-with-openai-realtime)-økter, inkludert økter
  for en lagret agent;
- innebygde konfigurasjoner returnert av en webhook for
  [dynamisk anropskonfigurasjon](/nb/guides/dynamic-call-config).
  En webhook som returnerer en `agent_id`, bruker trinnene til den agenten.

## Grenser

| Grense | Verdi |
| --- | --- |
| Trinn per agent | 100 |
| Innsamlede verdier per trinn | 20 |
| Viderekoblingsmål per agent | 8 |
| Agenter som kan nås i én samtale | 8 |
| Størrelse på `steps`-JSON-en | 200 KB |
| `instructions` for trinn | 20 000 tegn |
| `say`-linje | 1 000 tegn |
| Lagret resultat fra `on_enter_tool` | 4 KB |

En lagring som bryter en regel, returnerer `400` med stien til feltet som er
feil, for eksempel `steps.steps[2].transitions[0].to`. Verktøynavn i `tools` og
`on_enter_tool` må være verktøy som er knyttet til agenten.

Språk per trinn, skriptede trinn som hopper over modellen, og innsamlede verdier
i say-linjer støttes ikke.

## Importerte agenter

[Import](/nb/guides/import-agents) fra Retell, Bland, Vapi eller ElevenLabs
overfører agenter med flere instruksjoner, flyter, stier og arbeidsflyter som
trinn, og grupper og agentoverføringer som viderekoblinger mellom de importerte
agentene. Gjennomgangssiden viser begge deler før du importerer.

## Eksempel: pasientinntak hos tannlege

Tre trinn i rekkefølge: hils, samle inn pasientopplysninger, bestill.

```json
{
  "prompt": "You are Ava, the front desk assistant at Acme Dental. Be warm and brief. Ask one question at a time.",
  "steps": {
    "start_step": "greet",
    "steps": [
      {
        "id": "greet",
        "name": "Greeting",
        "instructions": "Greet the caller and ask how you can help.",
        "say": "Thanks for calling Acme Dental, this is Ava. How can I help you today?",
        "tools": null,
        "collect": [],
        "transitions": [
          {"to": "details", "when": "The caller wants to book an appointment"}
        ]
      },
      {
        "id": "details",
        "name": "Patient details",
        "instructions": "Ask for the caller's full name, date of birth and the reason for the visit. Read the date of birth back and ask the caller to confirm it.",
        "tools": null,
        "collect": [
          {"name": "full_name", "type": "string", "description": "Caller's full name", "required": true},
          {"name": "dob", "type": "date", "description": "Date of birth", "required": true},
          {"name": "reason", "type": "string", "description": "Reason for the visit", "required": true},
          {"name": "new_patient", "type": "boolean", "description": "First visit to the practice", "required": false}
        ],
        "transitions": [
          {"to": "book", "when": "The caller has confirmed their details"}
        ]
      },
      {
        "id": "book",
        "name": "Book",
        "instructions": "Offer the two earliest open slots from book_slot and book the one the caller picks. Confirm the date and time, then say goodbye and end the call.",
        "tools": ["book_slot"],
        "collect": [],
        "transitions": []
      }
    ]
  }
}
```

Klargjør den med `PATCH /v1/agents/{agent_id}`, prøv den med **Snakk**, og
distribuer den deretter. Trinnet `details` kan ikke gå videre til bestilling før
navn, fødselsdato og årsak er samlet inn. `new_patient` er valgfritt.

## Eksempel: en gren med aldersgrense

Modellen kan snakke med hvem som helst, men kode avgjør hvem som får bestille.
Samle inn alder, og styr deretter flyten basert på den før modellens eget valg
vurderes.

```json
{
  "id": "verify",
  "name": "Verify age",
  "instructions": "Ask for the caller's age.",
  "tools": null,
  "collect": [
    {"name": "age", "type": "number", "description": "Caller's age in years", "required": true}
  ],
  "transitions": [
    {"to": "guardian", "condition": {"value": "age", "op": "lt", "target": 18}},
    {"to": "book", "when": "The caller has given their age"}
  ]
}
```

En innringer som sier femten, går til `guardian`, uansett hva modellen
bestemmer. Alle andre går til `book`. Begge er vanlige trinn andre steder i
grafen.

## Eksempel: webhook-trinn for kontooppslag

Innringeren oppgir et kontonummer, oppslaget kjører når neste trinn åpnes,
og resultatet velger ruten. Trinnene `not_found`, `collections` og `support`
er utelatt for korthets skyld.

```json
[
  {
    "id": "identify",
    "name": "Identify",
    "instructions": "Ask for the caller's account number and read it back digit by digit.",
    "tools": null,
    "collect": [
      {"name": "account_number", "type": "string", "description": "Account number", "required": true}
    ],
    "transitions": [
      {"to": "lookup", "when": "The caller has confirmed their account number"}
    ]
  },
  {
    "id": "lookup",
    "name": "Look up account",
    "instructions": "Tell the caller what you found on their account and ask how you can help.",
    "tools": ["lookup_account"],
    "collect": [],
    "on_enter_tool": "lookup_account",
    "transitions": [
      {"to": "not_found", "condition": {"value": "lookup_account_result.response.found", "op": "eq", "target": false}},
      {"to": "collections", "condition": {"value": "lookup_account_result.response.account_status", "op": "in", "target": ["past_due", "suspended"]}},
      {"to": "support", "when": "The caller needs help with an active account"}
    ]
  }
]
```

`lookup_account` mottar `account_number` fordi parameteren har det
navnet. Hvis svarteksten inneholder `"found": false`, går samtalen til
`not_found`. Hvis `account_status` er `past_due` eller `suspended`, går den til
`collections`. En aktiv konto blir værende i `lookup`, der modellen hjelper og
går videre til `support`. Hvis du vil sende et mislykket oppslag til et eget trinn,
legger du først til betingelser for statusen: Et feilsvar lagrer statuskoden, så
`{"value": "lookup_account_result.status", "op": "gte", "target": 400}`
fanger den opp, og tidsavbrudd eller manglende svar lagrer `"error"`, så
`{"value": "lookup_account_result.status", "op": "eq", "target": "error"}`
fanger opp det.

## Eksempel: resepsjon til fakturering

To agenter. Resepsjonen (agent `412`) svarer på alle samtaler og videresender
spørsmål om fakturering til en faktureringsagent (agent `413`) med egen prompt, egne verktøy og stemme.

I resepsjonen:

```json
{
  "handoffs": [
    {"agent_id": 413, "when": "The caller asks about a bill, a payment or a refund"}
  ]
}
```

På faktureringsagenten, slik at den kan videresende innringeren tilbake:

```json
{
  "handoffs": [
    {"agent_id": 412, "when": "The billing question is resolved and the caller needs something else"}
  ]
}
```

Resepsjonen sier en kort setning, for eksempel «La meg sette deg over til
faktureringsteamet vårt», og faktureringsagenten presenterer seg og fortsetter
samtalen der resepsjonen slapp. Når fakturering videresender tilbake, fortsetter
resepsjonen der den var, uten å hilse på innringeren igjen. Samtalens produkt,
språk, samtykkevarsel og andre samtaleinnstillinger forblir hos resepsjonen,
fordi den svarte.

Hvis fakturering bare trenger egne instruksjoner og ikke en egen agent, bruker du
et globalt trinn i resepsjonen i stedet. Når spørsmålet er besvart, går samtalen
tilbake til trinnet innringeren var i:

```json
{
  "id": "billing",
  "name": "Billing questions",
  "instructions": "Answer questions about bills and payments. Offer to send a payment link by email.",
  "tools": null,
  "collect": [],
  "transitions": [
    {"to": "__previous__", "when": "The billing question is answered"}
  ],
  "global_when": "The caller asks about a bill or payment at any point"
}
```

## Neste trinn

<CardGroup cols={2}>
  <Card title="Veiledning for prompting" icon="pen" href="/nb/guides/prompting">
    Skriv delte instruksjoner og trinninstruksjoner som fungerer godt på telefon.
  </Card>
  <Card title="Bygg en verktøyintegrasjon" icon="code" href="/nb/guides/build-tool-integration">
    Opprett verktøyene som trinnene dine og webhook-trinnene dine kaller.
  </Card>
  <Card title="Test stemmeagentene dine" icon="flask" href="/nb/guides/test-agents">
    Kjør de samme scenarioene mot hver gren før du distribuerer.
  </Card>
  <Card title="Agents API" icon="robot" href="/api-reference/agents">
    Alle agentfelt, utkast og distribusjon.
  </Card>
</CardGroup>
