> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thunderphone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Byg en værktøjsintegration (API)

> Lad din agent kalde dine API'er midt i samtalen — søg i en database, opret en sag, slå en ordre op.

En **værktøjsintegration** er et genanvendeligt HTTP-slutpunkt, som en agent kan
kalde under et opkald. Du giver ThunderPhone en JSON-schema-beskrivelse
af værktøjet samt en slutpunkts-URL; agenten beslutter, hvornår det skal kaldes,
baseret på samtalen, og ThunderPhone udfører den udgående HTTP-anmodning
fra sine servere og returnerer svaret til agenten.

<Note>
  Dashboardet dækker de fleste værktøjsbehov uden dette API: **Forbindelser
  → Apps** forbinder Slack, HubSpot, Salesforce, Google Kalender,
  Google Sheets og Cal.com med få OAuth-klik; **Forbindelser →
  API'er** gør ethvert HTTP-API til en agenthandling (indsæt en cURL-kommando,
  og en AI-guide udarbejder værktøjet med en indbygget Testanmodning); og
  **Forbindelser → MCP** tilføjer MCP-servere. Se
  [Forbindelser](/da/guides/concepts). Denne vejledning beskriver det underliggende
  rå API bag API-grænsefladen.
</Note>

Denne vejledning gennemgår opbygningen af et værktøj til vejroplysninger fra start til slut.

## Et værktøjs opbygning

To dele:

1. **Schemaet** — en funktionsdefinition i OpenAI-stil
   (`{type: "function", function: {name, description, parameters}}`)
   der fortæller LLM'en, hvad værktøjet gør, og hvilke argumenter det tager.
2. **Slutpunktet** — den URL, ThunderPhones servere kalder, når
   LLM'en beslutter at bruge værktøjet. Anmodningen er en JSON POST med
   LLM'ens valgte argumenter som brødtekst.

## 1. Vælg en lagringsstrategi

<CardGroup cols={2}>
  <Card title="Indlejret på agenten" icon="paperclip">
    Tilknyt et enkeltstående værktøj til agentens `tools`-array. Simpelt, men
    ikke genanvendeligt.
  </Card>

  <Card title="Gemt integration" icon="plug">
    Gem værktøjet som en genanvendelig [integration](/api-reference/integrations)
    og tilknyt det fra mange agenter. Anbefales til alt, der bruges mere
    end én gang.
  </Card>
</CardGroup>

Denne vejledning bruger stien med gemt integration.

## 2. Opret integrationen

```bash theme={null}
curl -X POST https://api.thunderphone.com/v1/integrations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Weather API",
    "spec": {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a zip code.",
        "parameters": {
          "type": "object",
          "properties": {
            "zip": { "type": "string", "description": "5-digit US ZIP code" }
          },
          "required": ["zip"]
        }
      }
    },
    "endpoint_url":    "https://api.example.com/weather",
    "endpoint_method": "GET",
    "headers": [
      { "key": "X-Api-Key", "value": "your-provider-key" }
    ]
  }'
```

Gem det returnerede `id` (en UUID).

<Tip>
  Brug reel tid på `description` for værktøjet og hver
  parameter. LLM'en bruger disse strenge under kørsel til at afgøre, om
  og hvordan værktøjet skal kaldes. Vage beskrivelser → vage værktøjskald.
</Tip>

## 3. Sandbox-test slutpunktet

Før du tilknytter integrationen til en agent, skal du sende en signeret anmodning
fra ThunderPhones servere for at bekræfte forbindelsen:

```bash theme={null}
curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url":    "https://api.example.com/weather?zip=94110",
    "method": "GET",
    "headers": { "X-Api-Key": "your-provider-key" }
  }'
```

```json Response theme={null}
{
  "ok": true,
  "status": 200,
  "elapsed_ms": 187,
  "response_headers": { "content-type": "application/json" },
  "response_preview": "{\"temperature_f\": 64, ...}"
}
```

Denne test styrker også ThunderPhones SSRF-beskyttelse — anmodninger til
localhost eller private IP-områder returnerer `400 code=url_not_allowed`.

## 4. Knyt integrationen til en agent

Tilknyt via `integration_ids`, når du opretter eller opdaterer en agent:

```bash theme={null}
curl -X PATCH https://api.thunderphone.com/v1/agents/12 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "integration_ids": ["f9b5a1a4-..."]
  }'
```

Du kan knytte mange integrationer til én agent. Agentens prompt kan
henvise til dem ved navn — "brug `get_weather`, når opkalderen spørger
om forholdene" — eller den kan finde dem implicit ud fra
skemabeskrivelserne.

## 5. Implementer endpointet

Når agenten kalder værktøjet, sender ThunderPhone en signeret POST til
din `endpoint_url`:

```
POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json

{"zip": "94110"}
```

Din server svarer med JSON, som sendes tilbage til LLM'en:

```json theme={null}
{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}
```

LLM'en behandler svaret og giver opkalderen en menneskeligt formuleret
opsummering.

<Warning>
  Signaturen beregnes over den rå anmodningsbody med den samme
  `secret` som dit webhook-endpoint. **Bekræft den** — værktøjsendpoints
  er eksponeret på internettet og er udsat for de samme risici for
  forfalskning som webhooks. Se
  [Bekræft webhook-signaturer](/da/guides/verify-webhook-signatures).
</Warning>

## 6. Test forløbet

Kør en [mikrofonsession](/api-reference/mic-sessions) mod agenten, og
stil det spørgsmål, som dit værktøj håndterer ("Hvad er vejret i
94110?"). Opkaldets transskription viser hele forløbet:

```json theme={null}
{
  "call_id": 987654321,
  "transcripts": [
    { "role": "user",
      "content": "What's the weather in 94110?" },
    { "role": "tool_call",
      "content": "{\"tool_call\": \"get_weather\", \"arguments\": {\"zip\": \"94110\"}}" },
    { "role": "tool_response",
      "content": "{\"tool_name\": \"get_weather\", \"response\": {\"temperature_f\": 64, \"condition\": \"Partly cloudy\"}}" },
    { "role": "agent",
      "content": "It's 64 degrees and partly cloudy." }
  ]
}
```

Du kan hente dette via
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript);
den rå hændelsesstrøm (med tidsangivelser og lydforskydninger pr. post) findes på
[`GET /v1/calls/{call_id}/history`](/api-reference/calls#get-history).

## Almindelige faldgruber

<AccordionGroup>
  <Accordion title="Agenten kalder aldrig værktøjet">
    LLM'en beslutter ud fra værktøjets beskrivelse. Hvis opkalderens
    spørgsmål ikke matcher beskrivelsen, kalder modellen ikke
    værktøjet. Gør beskrivelsen mere præcis (tilføj almindelige
    synonymer og formuleringer), eller nævn det eksplicit i agentens
    prompt ("Når opkalderen spørger om vejret, skal du bruge
    `get_weather`.").
  </Accordion>

  <Accordion title="Værktøjet returnerer for mange data">
    Svar over 6 kB afkortes i forhåndsvisningen af transskriptionen. Returner
    kun de felter, som LLM'en har brug for — ikke hele din række.
  </Accordion>

  <Accordion title="Tidsudløb">
    Værktøjsendpoints har en standardtimeout på 10 sekunder. Hvis du har brug for længere tid,
    skal du håndtere det asynkront: returner `{"status": "pending", "request_id": "..."}`
    og vis resultatet via et separat værktøjskald.
  </Accordion>

  <Accordion title="Versionsstyring">
    Hver `PATCH` af en integration opretter en ny revision. Undersøg
    [`GET /v1/integrations/{id}/versions`](/api-reference/integrations#version-history)
    for at se, hvem der ændrede hvad. Hvis du ødelægger et værktøjs skema, kan du
    rulle tilbage manuelt ved at PATCH'e et ældre snapshot tilbage.
  </Accordion>
</AccordionGroup>

***

## Næste trin

<CardGroup cols={2}>
  <Card title="Reference til integrationer" icon="plug" href="/api-reference/integrations">
    CRUD, overførsel, versionshistorik.
  </Card>

  <Card title="Specifikation for funktionsværktøjer" icon="screwdriver-wrench" href="/da/tools/overview">
    Fuld JSON-schema-grammatik og kontrakten for signerede endpoints.
  </Card>

  <Card title="Bekræft signaturer" icon="shield-check" href="/da/guides/verify-webhook-signatures">
    Anvend mønstret for webhook-signaturer på værktøjsendpoints.
  </Card>

  <Card title="API til transskription + historik" icon="phone" href="/api-reference/calls">
    Undersøg hele tur-retur-forløbet for et værktøjskald.
  </Card>
</CardGroup>
