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

# Agent-Tool-Beispiele

> Typische KI-Agenten-Aufgaben auf Public API v1 Endpoints und Tool-Definitionen mappen.

Diese Muster richten sich an Entwickler, die **KI-Agenten-Tools** (OpenAI Function Calling, Claude Tools, LangChain usw.) auf der Public API aufbauen. Jeder Workflow braucht höchstens zwei Listen-Aufrufe, bevor du ins Detail gehst.

Voraussetzung: API-Schlüssel mit `tickets:read`. Siehe [Authentifizierung](/de/api/authentication).

## Kern-Tool-Set

Die meisten Agent-Integrationen exponieren vier Tools:

| Tool                  | API-Aufruf                                                |
| --------------------- | --------------------------------------------------------- |
| `list_inbox_views`    | `GET /public/v1/views`                                    |
| `list_tickets`        | `GET /public/v1/tickets` (+ optional `view_id`, `cursor`) |
| `get_ticket`          | `GET /public/v1/tickets/:ticketNumber`                    |
| `get_ticket_messages` | `GET /public/v1/tickets/:ticketNumber/messages?order=asc` |

Schemas: [Scalar](https://api.armin.cx/docs/v1).

***

## Use Case 1 — „Zeig offene Tickets der letzten 7 Tage“

Gespeicherte Ansichten kodieren Filter. Der Agent listet Views, wählt eine passende (offen + recent), listet Tickets.

**Schritte:**

1. `GET /public/v1/views` — `name` und `filters` nach passender Ansicht durchsuchen.
2. `GET /public/v1/tickets?view_id=<uuid>&limit=40` — Ticket-Zusammenfassungen ans LLM oder den Nutzer.

Gibt es keine passende Ansicht: Nutzer bitten, eine in [Posteingang-Ansichten](/de/inbox/views-and-filters) anzulegen — v1 kann keine Ad-hoc-Datums-/Status-Filter.

***

## Use Case 2 — „Fasse Ticket #1234 zusammen“

**Schritte:**

1. `GET /public/v1/tickets/1234/messages?order=asc&limit=100` — chronologischer Thread.
2. `messages[].text` konkatenieren (max. 10.000 Zeichen pro Nachricht) und ans eigene LLM-Summarization geben.

Optional vorher: `GET /public/v1/tickets/1234` für Betreff, Status, Kontakt, Tags.

Interne Notizen, Entwürfe und System-Events sind in Message-Responses **ausgeschlossen**.

***

## Use Case 3 — „Wie viele offene Tickets in meiner Retouren-Ansicht?“

**Nicht** alle Tickets paginieren zum Zählen. Nutze `count` der Ansicht:

**Schritte:**

1. `GET /public/v1/views` — Ansicht mit `name` „Retouren“ (o. ä.) finden.
2. `count` aus dem View-Objekt lesen.

```json theme={null}
{
  "id": "019b...",
  "name": "Retouren",
  "count": 42,
  "filters": [ ... ]
}
```

`count` kann einige Sekunden hinter dem Posteingang liegen (Read-Replica).

***

## OpenAI Tool-Definitionen (Beispiel)

```json theme={null}
[
  {
    "type": "function",
    "function": {
      "name": "list_inbox_views",
      "description": "Gespeicherte Posteingang-Ansichten mit Filtern und Ticket-Anzahl. Vor list_tickets nutzen, wenn der Nutzer eine Ansicht oder Filter (offen, Retouren, Kanal) meint.",
      "parameters": {
        "type": "object",
        "properties": {
          "limit": { "type": "integer", "description": "Max. Ansichten pro Seite (1-100)", "default": 50 },
          "cursor": { "type": "string", "description": "Pagination-Cursor aus vorherigem Aufruf" }
        }
      }
    }
  },
  {
    "type": "function",
    "function": {
      "name": "list_tickets",
      "description": "Support-Tickets listen. view_id aus list_inbox_views für gespeicherte Filter.",
      "parameters": {
        "type": "object",
        "properties": {
          "view_id": { "type": "string", "description": "UUID einer gespeicherten Ansicht" },
          "limit": { "type": "integer", "default": 40 },
          "cursor": { "type": "string" },
          "include_ticket_fields": { "type": "boolean", "default": false }
        }
      }
    }
  },
  {
    "type": "function",
    "function": {
      "name": "get_ticket_messages",
      "description": "Konversationsverlauf per Ticketnummer (z. B. 1234). order asc für Zusammenfassung.",
      "parameters": {
        "type": "object",
        "properties": {
          "ticket_number": { "type": "integer", "description": "Lesbare Ticketnummer" },
          "order": { "type": "string", "enum": ["asc", "desc"], "default": "asc" },
          "limit": { "type": "integer", "default": 30 },
          "cursor": { "type": "string" }
        },
        "required": ["ticket_number"]
      }
    }
  }
]
```

**Handler-Mapping:**

```typescript theme={null}
const BASE = 'https://api.armin.cx/public/v1'
const headers = { 'cx-api-key': process.env.CX_API_KEY! }

async function list_inbox_views(args: { limit?: number; cursor?: string }) {
  const params = new URLSearchParams()
  if (args.limit) params.set('limit', String(args.limit))
  if (args.cursor) params.set('cursor', args.cursor)
  const res = await fetch(`${BASE}/views?${params}`, { headers })
  return res.json()
}

async function list_tickets(args: {
  view_id?: string
  limit?: number
  cursor?: string
  include_ticket_fields?: boolean
}) {
  const params = new URLSearchParams()
  if (args.view_id) params.set('view_id', args.view_id)
  if (args.limit) params.set('limit', String(args.limit))
  if (args.cursor) params.set('cursor', args.cursor)
  if (args.include_ticket_fields) params.set('include', 'ticket_fields')
  const res = await fetch(`${BASE}/tickets?${params}`, { headers })
  return res.json()
}

async function get_ticket_messages(args: {
  ticket_number: number
  order?: 'asc' | 'desc'
  limit?: number
  cursor?: string
}) {
  const params = new URLSearchParams()
  if (args.order) params.set('order', args.order)
  if (args.limit) params.set('limit', String(args.limit))
  if (args.cursor) params.set('cursor', args.cursor)
  const res = await fetch(
    `${BASE}/tickets/${args.ticket_number}/messages?${params}`,
    { headers },
  )
  return res.json()
}
```

***

## Claude Tool-Definitionen (Beispiel)

```json theme={null}
{
  "name": "list_inbox_views",
  "description": "Gespeicherte Posteingang-Ansichten. Liefert id, name, count, filters. Aufrufen, wenn der Nutzer eine Ansicht nach Name meint oder gefilterte Ticket-Listen will.",
  "input_schema": {
    "type": "object",
    "properties": {
      "limit": { "type": "integer", "maximum": 100 },
      "cursor": { "type": "string" }
    }
  }
}
```

Gleiche HTTP-Handler wie oben. Claude-`tool_result` sollte den API-Body unverändert durchreichen (`success`, `data`, `pagination`).

***

## Tipps für Agent-Design

* **View-Namen in Tool 1 auflösen** — Modell wählt `view_id` aus `list_inbox_views`, statt UUIDs zu hardcoden.
* **Ticketnummern nutzerseitig** — URLs verwenden `#1234` / `ticket_number`, nicht UUIDs.
* **Lange Threads paginieren** — bei `has_more: true` `pagination.next_cursor` folgen.
* **404 sinnvoll behandeln** — `VIEW_NOT_FOUND` oft fehlende Agent-Sichtbarkeit; Service-Schlüssel oder andere Ansicht vorschlagen.
* **Rate Limits beachten** — View-Listen cachen; nicht jeden Turn neu laden.

## Verwandt

* [Filtern & gespeicherte Ansichten](/de/api/filtering-and-saved-views)
* [Pagination](/de/api/pagination)
* [Erste Schritte](/de/api/getting-started)
