So statten Sie einen KI-Agenten mit einem Transkriptions-Tool aus
Fassen Sie die zwei KolWrite-Aufrufe in einem Tool namens transcribe_media zusammen. Weiter unten stehen die Definitionen im tool-use-Format von Anthropic und im function-calling-Format von OpenAI, die ausführende Python-Funktion sowie eine minimale Tool-Schleife. Außerdem gibt es eine kurze Regel für AGENTS.md oder CLAUDE.md, damit Coding-Agenten die API richtig ansteuern.
Braucht man überhaupt eine eigene Tool-Definition?
Wenn Ihr Agent Shell-Befehle ausführen kann (Claude Code, Codex CLI, Cursor, Windsurf), braucht er kein Schema: Er führt curl oder Python aus, und die Anweisungen in agent-instructions.md sagen ihm, wie. Eine Tool-Definition ist für Agenten gedacht, die Sie mit einer API und einer Tool-Schleife bauen, oder für Frameworks, die Funktionen aufrufen.
Tool-Definition für Anthropic (Tool Use)
{
"name": "transcribe_media",
"description": "Transcribe an audio or video file with the KolWrite API. Returns timed text. Use output_format \"json\" for word timestamps and speakers, \"srt\" for subtitles, \"txt\" for plain text. Billed per second of audio.",
"input_schema": {
"type": "object",
"properties": {
"path_or_url": { "type": "string", "description": "Local file path or a public URL of an audio or video file." },
"model": { "type": "string", "enum": ["base", "oracle_mini", "oracle", "oracle_pro", "oracle_max"], "description": "Default oracle. base is cheapest for clear audio; translate_to needs an Oracle model." },
"language": { "type": "string", "description": "Language code such as en, he, ar, es, or auto to detect." },
"translate_to": { "type": "string", "description": "Language code to translate into (Oracle models only)." },
"output_format": { "type": "string", "enum": ["json", "txt", "srt"] },
"word_timestamps": { "type": "boolean", "description": "Word times in json. For srt, false gives one cue per segment." },
"include_diarization": { "type": "boolean", "description": "Label who is speaking." },
"num_speakers": { "type": "integer", "minimum": 1 }
},
"required": ["path_or_url"]
}
}
Tool-Definition für OpenAI (Function Calling)
{
"type": "function",
"function": {
"name": "transcribe_media",
"description": "Transcribe an audio or video file with the KolWrite API. Returns timed text. Use output_format \"json\" for word timestamps and speakers, \"srt\" for subtitles, \"txt\" for plain text. Billed per second of audio.",
"parameters": {
"type": "object",
"properties": {
"path_or_url": { "type": "string", "description": "Local file path or a public URL of an audio or video file." },
"model": { "type": "string", "enum": ["base", "oracle_mini", "oracle", "oracle_pro", "oracle_max"] },
"language": { "type": "string", "description": "Language code such as en, he, ar, es, or auto to detect." },
"translate_to": { "type": "string", "description": "Language code to translate into (Oracle models only)." },
"output_format": { "type": "string", "enum": ["json", "txt", "srt"] },
"word_timestamps": { "type": "boolean" },
"include_diarization": { "type": "boolean" },
"num_speakers": { "type": "integer", "minimum": 1 }
},
"required": ["path_or_url"]
}
}
}
Beide Varianten nutzen für die Parameter dasselbe JSON Schema. Im enum der Modelle stehen die aktuellen Versionen, während core und edge Legacy sind.
Die vom Tool ausgeführte Funktion
Die Ausführungsfunktion lädt lokale Dateien hoch, startet den Auftrag, wartet ab und gibt eine kompakte Antwort zurück. Bei JSON legt sie das vollständige Ergebnis in einer Datei ab und gibt nummerierte Zeilen zurück. Die gesamte Wortliste einer langen Aufnahme ist nämlich viel größer, als das Modell braucht.
kolwrite.py
# kolwrite.py — three small functions around the KolWrite REST API
import os, time, requests
API = "https://app.kolwrite.com"
HEADERS = {"x-api-key": os.environ["KOLWRITE_API_KEY"]}
def upload(path):
"""Upload a local file (up to 100 MiB) and return a URL the API can read."""
name = os.path.basename(path)
form = requests.post(f"{API}/upload", headers=HEADERS, json={"filename": name}, timeout=30)
form.raise_for_status()
form = form.json()
with open(path, "rb") as media:
# No x-api-key on this request: it goes to the storage address.
sent = requests.post(form["uploadUrl"], data=form["uploadFields"],
files={"file": (name, media)}, timeout=600)
sent.raise_for_status()
return form["fileUrl"]
def transcribe(audio_url, timeout_s=3600, **options):
"""Start a job, wait for it, return the result: a dict for json, a string for srt and txt."""
body = {"audio_url": audio_url, "model": "oracle", **options}
job = requests.post(f"{API}/transcribe", headers=HEADERS, json=body, timeout=30)
job.raise_for_status()
job_id = job.json()["jobId"]
deadline = time.time() + timeout_s
while time.time() < deadline:
time.sleep(5)
reply = requests.get(f"{API}/transcribe/{job_id}", headers=HEADERS, timeout=30)
reply.raise_for_status()
reply = reply.json()
if reply["status"] == "COMPLETED":
return reply["result"]
if reply["status"] == "FAILED":
raise RuntimeError(reply.get("error", "transcription failed"))
raise TimeoutError(f"job {job_id} did not finish in {timeout_s} seconds")
tool.py
# tool.py — run a transcribe_media call for the model and keep the reply small
import json
from kolwrite import upload, transcribe # the helper from the video-editing guide
def numbered_line(number, segment):
who = f'{segment["speaker"]}: ' if segment.get("speaker") else ""
return f'S{number} [{segment["start"]:.1f}-{segment["end"]:.1f}] {who}{segment["text"]}'
def run_transcribe_media(path_or_url, output_format="json", **options):
url = path_or_url if path_or_url.startswith(("http://", "https://")) else upload(path_or_url)
result = transcribe(url, output_format=output_format, **options)
if output_format != "json":
return result # srt and txt are already strings
# Long recordings: save the full JSON and hand the model numbered lines, not 500 KB of words.
with open("transcript.json", "w", encoding="utf-8") as out:
json.dump(result, out, ensure_ascii=False)
lines = [numbered_line(i, s) for i, s in enumerate(result["segments"])]
return "Full JSON saved to transcript.json (words[] has word times).\n" + "\n".join(lines)
Eine minimale Ausführungsschleife (Anthropic Messages API)
# loop.py — Anthropic Messages API tool loop around run_transcribe_media
import anthropic
from tool import run_transcribe_media
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
TOOLS = [...] # the transcribe_media definition above
messages = [{"role": "user", "content": "Transcribe interview.mp3 and list the questions asked, with times."}]
while True:
reply = client.messages.create(model="YOUR_MODEL", max_tokens=2000, tools=TOOLS, messages=messages)
messages.append({"role": "assistant", "content": reply.content})
if reply.stop_reason != "tool_use":
print("".join(block.text for block in reply.content if block.type == "text"))
break
results = []
for block in reply.content:
if block.type == "tool_use" and block.name == "transcribe_media":
results.append({"type": "tool_result", "tool_use_id": block.id,
"content": run_transcribe_media(**block.input)})
messages.append({"role": "user", "content": results})
Tragen Sie statt YOUR_MODEL die von Ihnen genutzte Modell-ID ein. Die Schleife läuft so lange weiter, bis das Modell keine Tools mehr anfordert. Derselbe Ausführer klappt mit jedem Framework, das eine Python-Funktion aufrufen kann.
Eintrag für AGENTS.md und CLAUDE.md
Kopieren Sie diesen Abschnitt in die Konfigurationsdatei Ihres Coding-Agenten. So weiß er in jeder Sitzung, welchen Endpunkt, welche Formate und welchen Weg für den API-Schlüssel er nutzen soll:
## Transcription
For speech-to-text, subtitles and word timings use the KolWrite API (https://app.kolwrite.com).
Before writing code read https://console.kolwrite.com/agent-instructions.md and /llms-full.txt.
- Key: KOLWRITE_API_KEY in the environment, sent as the x-api-key header. Never print it or commit it.
- POST /transcribe {"audio_url", "model": "oracle", "output_format": "json"}, then poll GET /transcribe/{jobId}.
- Local files: POST /upload first and use fileUrl as audio_url. Extract audio from video with ffmpeg to stay under 100 MiB.
- Subtitles: output_format "srt" with "word_timestamps": false (one cue per segment). Formats are json, txt, srt only.
- Always send "model". Ask me before transcribing anything longer than one hour: it costs money.
Kostenkontrolle beim Einsatz von Agenten
- Die Transkription wird pro Sekunde Audio abgerechnet und beginnt bei 0,48 US$ pro Stunde mit
base. Durch die obige Regel fragt der Agent bei langen Dateien vorher nach. - Ergebnisse zwischenspeichern: Legen Sie das JSON direkt neben der Mediendatei ab und nutzen Sie es wieder, statt die Datei noch einmal zu transkribieren.
- Wählen Sie das günstigste Modell, das für Ihren Fall ausreicht:
basebei klarem Audio,oraclefür Produktionsqualität undoracle_mini, wenn Sie zusätzlich eine Übersetzung brauchen. - Das Konto und den API-Schlüssel muss ein Mensch anlegen, da sich ein Agent nicht selbst registrieren kann. Übergeben Sie dem Agenten den Schlüssel als Umgebungsvariable.
Fragen und Antworten
Gibt es ein SDK oder einen MCP-Server für KolWrite?
Zum Zeitpunkt der Veröffentlichung sind weder ein SDK-Paket noch ein MCP-Server veröffentlicht. Die API ist HTTPS und JSON; nutzen Sie die Tool-Definition oben, curl oder Python direkt oder erzeugen Sie einen Client aus openapi.json.
Wie lasse ich Claude Code Audio transkribieren?
Legen Sie den Schlüssel in KOLWRITE_API_KEY, fügen Sie die Regel oben in CLAUDE.md ein und bitten Sie um die Transkription. Claude Code ruft die REST-API mit curl oder Python auf, nach agent-instructions.md.
Welches Modell sollte ein Agent standardmäßig wählen?
Nehmen Sie oracle für Produktionsaudio. Bei klarem Audio ist base am günstigsten, und oracle_mini ist das preiswerteste Modell mit Übersetzungsfunktion. Geben Sie den Parameter model immer ausdrücklich mit, sonst greift als Standard das veraltete core.
Kann der Agent seinen eigenen API-Schlüssel erstellen?
Nein. Ein Mensch muss sich auf console.kolwrite.com registrieren, Credits kaufen und den Schlüssel erstellen. Der Agent liest ihn dann nur noch aus der Umgebungsvariable aus.