Function calling
Let OpenAI, Anthropic, Gemini or any model with tool calling translate through FluentC. A tool definition, a handler that calls the REST API, and the full loop.
Any model that supports tool calling can use FluentC. You describe a translate_text tool to the model; when the model asks for it, your code calls the REST API and sends the result back. The model never sees your API key.
The tool definition
This is the tool as a JSON Schema. It is the same for every provider; only the wrapper differs.
{
"name": "translate_text",
"description": "Translate text into a target language using FluentC. Use it whenever the user asks for a translation or text must be shown in another language.",
"parameters": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "The text to translate."
},
"target_language": {
"type": "string",
"description": "Lowercase language code, such as fr, es, de or ja."
},
"source_language": {
"type": "string",
"description": "Optional. Language code of the text, if known."
}
},
"required": ["text", "target_language"]
}
}
How to wrap it:
| Provider | Wrapper |
|---|---|
| OpenAI (Chat Completions) | { "type": "function", "function": <the definition above> } in the tools array |
| Anthropic | { "name", "description", "input_schema": <the parameters object> } in the tools array |
| Others | Use the provider's function declaration format with the same JSON Schema |
The handler
The handler turns the model's arguments into a FluentC request. It returns the translation, or the error text, as the tool result.
import os
import requests
def translate_text(text, target_language, source_language=None):
body = {
"input": text,
"input_format": "text",
"target_language": target_language,
"mode": "real-time",
}
if source_language:
body["source_language"] = source_language
res = requests.post(
"https://api.fluentc.ai/ai_agent/translate",
headers={"Authorization": os.environ["FLUENTC_KEY"]},
json=body,
timeout=30,
)
data = res.json()
if not res.ok:
# Give the model the message so it can correct itself or tell the user.
return {"error": data.get("error", f"HTTP {res.status_code}")}
return {"translated_text": data["translation"]}
Returning errors as data, rather than raising, lets the model react: it can retry with a valid language code, or explain the problem. A key on the Batch plan can't use real-time; use batch and poll, as in Batch results.
The loop (OpenAI Chat Completions)
import json
import os
from openai import OpenAI
client = OpenAI()
MODEL = os.environ["OPENAI_MODEL"]
TOOLS = [{
"type": "function",
"function": {
"name": "translate_text",
"description": "Translate text into a target language using FluentC.",
"parameters": {
"type": "object",
"properties": {
"text": {"type": "string", "description": "The text to translate."},
"target_language": {"type": "string", "description": "Language code, such as fr."},
"source_language": {"type": "string", "description": "Optional source language code."},
},
"required": ["text", "target_language"],
},
},
}]
messages = [{"role": "user", "content": "How do I say 'How may I help?' in Japanese?"}]
while True:
response = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS)
message = response.choices[0].message
messages.append(message)
if not message.tool_calls:
print(message.content)
break
for call in message.tool_calls:
args = json.loads(call.function.arguments)
result = translate_text(**args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result, ensure_ascii=False),
})
ensure_ascii=False keeps non-Latin text readable to the model.
Same handler in Node
export async function translateText({ text, target_language, source_language }) {
const res = await fetch("https://api.fluentc.ai/ai_agent/translate", {
method: "POST",
headers: {
Authorization: process.env.FLUENTC_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
input: text,
input_format: "text",
target_language,
...(source_language && { source_language }),
mode: "real-time",
}),
});
const data = await res.json();
if (!res.ok) return { error: data.error ?? `HTTP ${res.status}` };
return { translated_text: data.translation };
}
Tips for reliable tool use
- Validate languages up front. Fetch Languages once and put the codes in the tool description or as an
enum, so the model can't pick one your key doesn't have. - Keep the key server-side. The handler runs in your code. Never put the key in a prompt or a tool description.
- Repeats are cheap. If the model asks for the same string twice, it is answered from translation memory.
- Large content. Translating a long document inside a conversation is slow. Hand the model a tool that submits a batch job and returns the
job_id, and a second tool that fetches the result. - Prefer an MCP server when the client supports it. The MCP server gives the model these tools without a handler to maintain.
Something unclear, or missing? Tell us.