Как подключить инструмент транскрипции к ИИ-агенту
Два базовых запроса к KolWrite удобно обернуть в единый инструмент transcribe_media. Ниже вы найдёте готовые схемы для Anthropic (tool-use) и OpenAI (function-calling), Python-функцию для выполнения запросов, минимальный рабочий цикл агента и короткую памятку для AGENTS.md или CLAUDE.md, чтобы ИИ-ассистенты правильно обращались к API.
Нужно ли вообще описывать инструмент?
Если ваш агент умеет выполнять команды оболочки (Claude Code, Codex CLI, Cursor, Windsurf), схема ему не нужна: он запускает curl или Python, а инструкции из agent-instructions.md объясняют, как. Описание инструмента нужно агентам, которых вы строите на API с циклом инструментов, или фреймворкам, вызывающим функции.
Схема инструмента для 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"]
}
}
Схема инструмента для 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"]
}
}
}
Внутри обеих обёрток используется одна и та же JSON Schema с параметрами. В список enum вынесены только актуальные модели, так как core и edge уже устарели.
Функция для выполнения инструмента
Исполнитель загружает локальные файлы, запускает задачу, дожидается её завершения и возвращает компактный ответ. В случае с JSON он сохраняет полный результат в файл, а в ответ отдаёт пронумерованные строки, так как весь список слов из длинной записи гораздо больше того, что требуется модели.
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)
Минимальный цикл работы с инструментом (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})
Подставьте вместо YOUR_MODEL идентификатор вашей модели. Цикл крутится до тех пор, пока модель не перестанет запрашивать инструменты. Тот же исполнитель подойдет для любого фреймворка, который умеет вызывать функции Python.
Инструкция для файлов AGENTS.md и CLAUDE.md
Скопируйте этот блок в конфигурационный файл вашего проекта, который читает ИИ-помощник. Так агент в каждой сессии будет сразу знать правильный эндпоинт, нужные форматы и правила работы с ключом:
## 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.
Как контролировать расходы агента
- Оплата за расшифровку списывается за каждую секунду аудио (от 0,48 $ в час на модели
base). Поэтому в инструкции выше прописано требование, чтобы перед отправкой длинных записей агент сначала спрашивал разрешение у пользователя. - Кешируйте ответы. Достаточно сохранить полученный JSON рядом с медиафайлом и брать данные оттуда, чтобы не запускать расшифровку повторно.
- Берите самую дешёвую из подходящих моделей:
baseхватит для чистого звука,oracleдаст продакшен-качество, аoracle_miniпригодится, если сразу нужен перевод. - Аккаунт и ключ API создаёт человек, сам агент зарегистрироваться не может. Передайте ему готовый ключ через переменную окружения.
Вопросы и ответы
Есть ли у KolWrite свой SDK или MCP-сервер?
На момент написания пакета SDK и сервера MCP не опубликовано. API — это HTTPS и JSON; используйте описание инструмента выше, curl или Python напрямую либо сгенерируйте клиент из openapi.json.
Как научить Claude Code расшифровывать аудио?
Положите ключ в KOLWRITE_API_KEY, добавьте правило выше в CLAUDE.md и попросите расшифровку. Claude Code вызовет REST API через curl или Python по agent-instructions.md.
Какую модель ставить агенту по умолчанию?
Для продакшена берите oracle. Если звук чистый, дешевле всего выйдет base, а для перевода самая доступная модель это oracle_mini. Всегда явно указывайте параметр model, иначе по умолчанию подставится устаревшая core.
Может ли агент сам выпустить себе ключ API?
Нет. Человек должен сам зарегистрироваться на console.kolwrite.com, пополнить счёт и выпустить ключ. Агент только забирает его из переменных окружения.