> ## 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.

# Bygg en verktygsintegration (API)

> Låt din agent anropa dina API:er mitt i ett samtal – sök i en databas, skapa ett ärende eller slå upp en beställning.

En **verktygsintegration** är en återanvändbar HTTP-slutpunkt som en agent kan
anropa under ett samtal. Du ger ThunderPhone en JSON-schema-beskrivning
av verktyget samt en slutpunkts-URL; agenten avgör när den ska anropa det
baserat på konversationen, och ThunderPhone gör det utgående HTTP-anropet
från sina servrar och returnerar svaret till agenten.

<Note>
  Instrumentpanelen täcker de flesta verktygsbehoven utan detta API: **Anslutningar
  → Appar** ansluter Slack, HubSpot, Salesforce, Google Calendar,
  Google Sheets och Cal.com med några få OAuth-klick; **Anslutningar →
  API:er** gör valfritt HTTP-API till en agentåtgärd (klistra in ett cURL-kommando
  så skapar en AI-guide ett utkast till verktyget, med inbyggt Testa begäran); och
  **Anslutningar → MCP** lägger till MCP-servrar. Se
  [Anslutningar](/sv/guides/concepts). Den här guiden beskriver det underliggande
  råa API:et bakom API-ytan.
</Note>

Den här guiden går igenom hur du bygger ett verktyg för väderuppslag från början till slut.

## Ett verktygs anatomi

Två delar:

1. **Schemat** — en funktionsdefinition i OpenAI-stil
   (`{type: "function", function: {name, description, parameters}}`)
   som talar om för LLM:en vad verktyget gör och vilka argument det tar.
2. **Slutpunkten** — URL:en som ThunderPhones servrar anropar när
   LLM:en beslutar att använda verktyget. Begäran är en JSON POST med
   LLM:ens valda argument som brödtext.

## 1. Välj en lagringsstrategi

<CardGroup cols={2}>
  <Card title="Infogat på agenten" icon="paperclip">
    Lägg till ett engångsverktyg i agentens `tools`-array. Enkelt, men
    inte återanvändbart.
  </Card>

  <Card title="Sparad integration" icon="plug">
    Lagra verktyget som en återanvändbar [integration](/api-reference/integrations)
    och länka det från flera agenter. Rekommenderas för allt som används mer
    än en gång.
  </Card>
</CardGroup>

Den här guiden använder vägen med sparad integration.

## 2. Skapa 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" }
    ]
  }'
```

Spara det returnerade `id`-värdet (en UUID).

<Tip>
  Lägg verklig omsorg på verktygets `description` och på varje
  parameter. LLM:en använder dessa strängar vid körning för att avgöra
  om och hur verktyget ska anropas. Vaga beskrivningar → vaga verktygsanrop.
</Tip>

## 3. Testa slutpunkten i sandlådan

Innan du länkar integrationen till en agent, skicka en signerad begäran
från ThunderPhones servrar för att bekräfta anslutningen:

```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, ...}"
}
```

Det här testet stärker även ThunderPhones SSRF-skydd — begäranden till
localhost eller privata IP-intervall returnerar `400 code=url_not_allowed`.

## 4. Koppla integrationen till en agent

Koppla den via `integration_ids` när du skapar eller uppdaterar 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 koppla många integrationer till en agent. Agentens prompt kan
referera till dem med namn — ”använd `get_weather` när uppringaren frågar
om väderförhållanden” — eller så kan den identifiera dem implicit utifrån
schemabeskrivningarna.

## 5. Implementera slutpunkten

När agenten anropar verktyget skickar ThunderPhone en signerad POST till
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 svarar med JSON som skickas tillbaka till LLM:

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

LLM tar emot svaret och ger uppringaren en sammanfattning på naturligt språk.

<Warning>
  Signaturen beräknas över det råa begärandeinnehållet med samma
  `secret` som din webhook-slutpunkt. **Verifiera den** — verktygsslutpunkter
  är exponerade mot internet och omfattas av samma risker för förfalskning som
  webhooks. Se
  [Verifiera webhooksignaturer](/sv/guides/verify-webhook-signatures).
</Warning>

## 6. Testa flödet

Starta en [mikrofonsession](/api-reference/mic-sessions) mot agenten
och ställ frågan som verktyget hanterar (”Hur är vädret i
94110?”). Samtalets transkription visar hela flödet tur och retur:

```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 hämta detta via
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript);
den råa händelseströmmen (med tidsangivelser och ljudförskjutningar per post) finns på
[`GET /v1/calls/{call_id}/history`](/api-reference/calls#get-history).

## Vanliga fallgropar

<AccordionGroup>
  <Accordion title="Agenten anropar aldrig verktyget">
    LLM fattar beslutet utifrån verktygets beskrivning. Om uppringarens
    fråga inte matchar beskrivningen anropar modellen inte
    verktyget. Förtydliga beskrivningen (lägg till vanliga synonymer och
    formuleringar) eller nämn det uttryckligen i agentens prompt (”När
    uppringaren frågar om väder, använd `get_weather`.").
  </Accordion>

  <Accordion title="Verktyget returnerar för mycket data">
    Svar över 6 kB trunkeras i transkriptionsförhandsvisningen. Returnera
    endast de fält som LLM behöver — inte hela dataraden.
  </Accordion>

  <Accordion title="Tidsgränser">
    Verktygsslutpunkter har en standardtidsgräns på 10 sekunder. Om du behöver längre tid
    hanterar du det asynkront: returnera `{"status": "pending", "request_id": "..."}`
    och visa resultatet via ett separat verktygsanrop.
  </Accordion>

  <Accordion title="Versionshantering">
    Varje `PATCH` av en integration skapar en ny revision. Kontrollera
    [`GET /v1/integrations/{id}/versions`](/api-reference/integrations#version-history)
    för att se vem som ändrade vad. Om du förstör ett verktygs schema kan du
    återställa manuellt genom att PATCH:a tillbaka en äldre ögonblicksbild.
  </Accordion>
</AccordionGroup>

***

## Nästa steg

<CardGroup cols={2}>
  <Card title="Referens för integrationer" icon="plug" href="/api-reference/integrations">
    CRUD, överföring, versionshistorik.
  </Card>

  <Card title="Specifikation för funktionsverktyg" icon="screwdriver-wrench" href="/sv/tools/overview">
    Fullständig JSON-schemagrammatik och kontraktet för signerade slutpunkter.
  </Card>

  <Card title="Verifiera signaturer" icon="shield-check" href="/sv/guides/verify-webhook-signatures">
    Tillämpa mönstret för webhook-signaturer på verktygsslutpunkter.
  </Card>

  <Card title="API för transkript + historik" icon="phone" href="/api-reference/calls">
    Granska hela tur- och returflödet för ett verktygsanrop.
  </Card>
</CardGroup>
