Internal Copilots

Internal Copilots

Run internal copilots on Clarke at $1.50 / $7.00 per 1M tokens, with streaming and tool calling. Change the base URL, key and model.

clarke-1.0
October 14, 2026
At a glance
Recommended model
Clarke
Model ID
clarke-1.0
Price per 1M tokens
$1.50 input / $7.00 output
Compatibility
OpenAI and Anthropic compatible APIs. Change the base URL, key and model.
Last updated
October 14, 2026

What drives the cost

An internal copilot is a chat assistant your team uses all day, inside the tools they already work in, answering questions about your own documents, tickets, code and data. Its cost behaves differently from a single API call, because a conversation resends its history on every turn and every tool call is another request to the model.

The cost of one call is the input tokens multiplied by the input price, plus the output tokens multiplied by the output price, divided by one million. Clarke costs $1.50 per million input tokens and $7.00 per million output tokens.

Two worked examples to replace with your own numbers

The first is a five-turn conversation in which the copilot searches the company wiki once per question. Each turn takes two calls: one in which the model decides to search, and one in which it reads the results and answers.

AssumptionValue
Instructions and tool definitions, sent on every call3,000 tokens
Question100 tokens
Search results returned by the tool4,000 tokens
Answer400 tokens
Turns per conversation5
Input tokens across the conversation61,250
Output tokens across the conversation2,250
Cost per conversation on Clarke$0.108

The first turn reads 10,250 input tokens and the fifth reads 14,250, because each turn carries the questions and answers before it. A company with 500 people using the copilot, each holding 3 conversations a working day, runs 31,500 conversations a month and pays about $3,390 on Clarke before prompt caching, or about $6.78 per person.

The second is a single question about a long document, such as a contract, a policy manual or a quarter of board notes, pasted into the conversation.

AssumptionValue
Document60,000 tokens
Instructions and question1,100 tokens
Answer800 tokens
Cost per question on Clarke$0.097

In the conversation example input is 85 percent of the cost, and the instructions and tool definitions alone are 49 percent of the input. They are identical on every call, which is the case prompt caching is built for, and Radium's model pages put the saving on repeated prompts at up to 90 percent. Anthropic's caching documentation lists long multi-turn conversations and repeated tool definitions among the cases it suits, and the same arithmetic applies on any provider. Trimming old turns and keeping tool results out of later turns does more for the bill than shortening answers.

Measure a week of real conversations before you plan around any of these numbers.

Which model to use

Clarke is the default for internal copilots. Radium built it for RAG, copilots, tool calling and structured outputs, and positions it as comparable to Sonnet 5.5 and GPT-6 Sol. It runs multi-step tool loops, streams its answers and tool calls, reads screenshots, and has a context window of 1,000,000 tokens, so a long document or a long conversation fits without splitting.

Hal takes the requests that need deeper reasoning, such as planning a migration across several systems, analyzing a set of documents against each other, or answering a hard question about code. It costs $2.25 per million input tokens and $13.75 per million output tokens, so the conversation above costs about $0.169 on Hal against $0.108 on Clarke. Most teams route to it with a button for a deeper answer or a classifier, and keep Clarke as the default.

Tycho does the work around the conversation. Use it to classify a question and pick the right tool or model, title a conversation, summarize old turns so the history stays short, and tag feedback. Titling a conversation from its first exchange costs about $0.00080. Radium's tool calling guide marks multi-step tool loops on Tycho as limited, so keep it off the main conversation.

StepModelModel ID
The conversation itself: answers, tool calls, document questionsClarkeclarke-1.0
Hard analysis, multi-system planning, difficult code questionsHalhal-1.0
Routing, conversation titles, history summaries, feedback taggingTychotycho-1.0

Start on Clarke and promote individual requests to Hal.

What this workload needs from the API

A copilot depends on more of the API surface than most workloads. Confirm each row against your own client before people start using it.

CapabilityWhy a copilot needs itOn Radium
StreamingShowing the answer as it is written, so the copilot feels fastSupported on all three models, in the OpenAI and Anthropic formats, including tool call deltas
Tool callingSearching the wiki, reading a ticket, querying a database in the middle of an answerParallel calls and strict schema validation on all three models. Multi-step loops on Hal and Clarke
Context windowHolding a long conversation or a whole documentClarke 1,000,000 tokens, Hal 250,000, Tycho 125,000. Oversized requests return a 400 with context_length_exceeded
Image inputAnswering questions about a pasted screenshot or chartHal and Clarke
Structured outputFilling a form, creating a ticket or returning an action your app can runJSON mode and JSON schema on all three models
Spend controlsKeeping one heavy user or a runaway loop from running up the billmax_tokens on every request and a per-request usage export from the dashboard. Budget alerts and limits are on Radium's roadmap

Four things do not carry over unchanged. Radium does not support the Responses API, so a copilot built on hosted conversation threads keeps its history in your own store and sends it with each request. Radium does not offer embeddings or hosted file search, so retrieval stays with your current embedding provider and vector database. Model names from other providers return a not-found error until you change them to a Radium model ID. Radium's tool calling guide notes minor differences in some less common OpenAI tool options, such as function_call set to none, so test the options you rely on.

Run your ten most used tools through the new endpoint before the pilot.

How to switch

Radium serves OpenAI-compatible and Anthropic-compatible APIs, so an existing copilot keeps its SDK, its prompts, its tool definitions and its streaming code. Three values change, which are the base URL, the API key and the model name.

Pick the SDK you already use, then your language. The Anthropic SDK adds the /v1 path itself, so its base URL does not include it. Replace YOUR_API_KEY with your key.

OpenAI SDK, Python
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.radium.cloud/v1",
)

response = client.chat.completions.create(
    model="clarke-1.0",
    messages=[
        {"role": "user", "content": "Hello, Radium!"}
    ],
)

print(response.choices[0].message.content)
OpenAI SDK, TypeScript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "YOUR_API_KEY",
  baseURL: "https://api.radium.cloud/v1",
});

const response: OpenAI.Chat.ChatCompletion =
  await client.chat.completions.create({
    model: "clarke-1.0",
    messages: [{ role: "user", content: "Hello, Radium!" }],
  });

console.log(response.choices[0].message.content);
OpenAI SDK, curl
curl https://api.radium.cloud/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "clarke-1.0",
    "messages": [{"role": "user", "content": "Hello, Radium!"}]
  }'
OpenAI SDK, Go
package main

import (
	"context"
	"fmt"

	openai "github.com/sashabaranov/go-openai"
)

func main() {
	cfg := openai.DefaultConfig("YOUR_API_KEY")
	cfg.BaseURL = "https://api.radium.cloud/v1"
	client := openai.NewClientWithConfig(cfg)

	resp, err := client.CreateChatCompletion(
		context.Background(),
		openai.ChatCompletionRequest{
			Model: "clarke-1.0",
			Messages: []openai.ChatCompletionMessage{
				{Role: openai.ChatMessageRoleUser, Content: "Hello, Radium!"},
			},
		},
	)
	if err != nil {
		panic(err)
	}

	fmt.Println(resp.Choices[0].Message.Content)
}
OpenAI SDK, Java
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.chat.completions.*;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .apiKey("YOUR_API_KEY")
    .baseUrl("https://api.radium.cloud/v1")
    .build();

ChatCompletion completion = client.chat().completions().create(
    ChatCompletionCreateParams.builder()
        .model("clarke-1.0")
        .addUserMessage("Hello, Radium!")
        .build());

System.out.println(
    completion.choices().get(0).message().content().orElseThrow());
OpenAI SDK, C#
using OpenAI;
using OpenAI.Chat;

var client = new OpenAIClient(
    new ApiKeyCredential("YOUR_API_KEY"),
    new OpenAIClientOptions
    {
        Endpoint = new Uri("https://api.radium.cloud/v1"),
    });

var chatClient = client.GetChatClient("clarke-1.0");
var response = await chatClient.CompleteChatAsync(
    new UserChatMessage("Hello, Radium!"));

Console.WriteLine(response.Value.Content[0].Text);
Anthropic SDK, Python
import anthropic

client = anthropic.Anthropic(
    api_key="YOUR_API_KEY",
    base_url="https://api.radium.cloud",
)

message = client.messages.create(
    model="clarke-1.0",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Hello, Radium!"}
    ],
)

print(message.content[0].text)
Anthropic SDK, TypeScript
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: "YOUR_API_KEY",
  baseURL: "https://api.radium.cloud",
});

const message: Anthropic.Message = await client.messages.create({
  model: "clarke-1.0",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello, Radium!" }],
});

console.log(message.content[0].text);
Anthropic SDK, curl
curl https://api.radium.cloud/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "clarke-1.0",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hello, Radium!"}]
  }'

A streaming answer with a tool call

This is the loop at the center of most copilots. Clarke streams its answer, and when it decides to search the wiki, the tool call arrives in pieces that the loop reassembles, runs and sends back, until the model answers without calling a tool. max_tokens caps every response.

Python, streaming copilot with a tool
import json
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.radium.cloud/v1",
)

tools = [{
    "type": "function",
    "function": {
        "name": "search_wiki",
        "description": "Search the company wiki and return the most relevant passages.",
        "parameters": {
            "type": "object",
            "properties": {"query": {"type": "string"}},
            "required": ["query"],
        },
    },
}]


def search_wiki(query):
    return "..."  # call your own search here


messages = [
    {"role": "system", "content": "Answer questions using the wiki and cite the page you used."},
    {"role": "user", "content": "How many days of parental leave do we offer?"},
]

while True:
    stream = client.chat.completions.create(
        model="clarke-1.0",
        messages=messages,
        tools=tools,
        max_tokens=1024,
        stream=True,
    )
    text, calls = "", {}
    for chunk in stream:
        if not chunk.choices:
            continue
        delta = chunk.choices[0].delta
        if delta.content:
            text += delta.content
            print(delta.content, end="", flush=True)
        for tc in delta.tool_calls or []:
            call = calls.setdefault(tc.index, {"id": "", "name": "", "arguments": ""})
            if tc.id:
                call["id"] = tc.id
            if tc.function and tc.function.name:
                call["name"] = tc.function.name
            if tc.function and tc.function.arguments:
                call["arguments"] += tc.function.arguments
    if not calls:
        break
    messages.append({
        "role": "assistant",
        "content": text or None,
        "tool_calls": [
            {"id": c["id"], "type": "function",
             "function": {"name": c["name"], "arguments": c["arguments"]}}
            for c in calls.values()
        ],
    })
    for c in calls.values():
        result = search_wiki(**json.loads(c["arguments"]))
        messages.append({"role": "tool", "tool_call_id": c["id"], "content": result})

Steps

  1. Create an account at deploy.radium.cloud and generate a key at deploy.radium.cloud/keys. New accounts get $25 in credit with no card required.
  2. Keep the key on your server. The copilot's front end talks to your backend, and your backend calls Radium, so the key never reaches a browser or an employee's laptop.
  3. Point one team's copilot at Radium behind a feature flag while everyone else stays on your current provider.
  4. Compare the two groups for a week, then widen the flag.

Switching back means turning the flag off. Guides for the OpenAI and Anthropic SDKs, LangChain, LangGraph, LlamaIndex, the Vercel AI SDK and PydanticAI are in the Radium docs.

How to test it on your team's questions

A copilot is judged by the people who use it, so test it on their questions. Before the pilot, collect 100 questions your team has actually asked, each with the document that holds the answer, and run them through your current model and through Clarke with the same prompt and tools.

  1. Check the answers against the source. For each question, record whether the answer is correct and whether the page it cites contains the answer. A right answer with the wrong citation still sends someone to the wrong place.
  2. Check the tool calls. Count how often the model picks the right tool, sends valid arguments and stops searching once it has the answer. Extra searches cost money and time on every turn.
  3. Ask questions the wiki cannot answer. Include 20 questions with no answer in your sources. The model should say so instead of guessing.
  4. Measure what people feel. Record time to first token and total time per answer at the 50th and 95th percentiles with streaming on, and read the cost per conversation from the usage export.

Then run the pilot with one team on each side and compare thumbs-up rates and how often people retry a question. Decide what counts as a pass before you look at the results.

When Radium is the wrong choice

Radium fits when you run your own copilot, through your own backend, and its usage is a meaningful share of your AI spend. There are cases where switching is the wrong move.

  • Your copilot is a product you bought. If the vendor chooses the model and does not let you set your own endpoint and key, there is nothing to switch.
  • Your copilot is built on hosted threads and file search. Radium does not offer the Responses API, embeddings or file search, so moving means keeping conversation state and retrieval in your own stack first.
  • You need the provider to enforce hard budgets per user or per team. Radium caps each request with max_tokens and reports usage per request, but budget alerts and limits are still on its roadmap, so per-user limits live in your own code for now.
  • Your usage is small. If the bill is a few hundred dollars a month, the evaluation will cost more than the switch saves.
  • Your security review requires a certification Radium has not published. Radium lists GDPR compliance and handles SOC 2 Type II, ISO 27001 and HIPAA questions through its security package, so request it before internal documents flow through the copilot.

If none of these apply, run the 100 questions.

Frequently asked questions

Can I run our internal copilot on Radium without rebuilding it?

Yes, if your copilot calls a model API from your own backend. Radium serves OpenAI-compatible and Anthropic-compatible APIs, so you change the base URL, the API key and the model name, and your prompts, tool definitions and streaming code stay the same. A copilot built on the Responses API needs to keep its own conversation history first, because Radium does not support that API.

Which Radium model should power an internal copilot?

Use Clarke (clarke-1.0) for the conversation itself, including tool calls and questions about long documents. Promote hard analysis and planning requests to Hal (hal-1.0). Use Tycho (tycho-1.0) for routing, conversation titles and summarizing old turns, because Radium marks multi-step tool loops on Tycho as limited.

How much does an internal AI copilot cost to run on Radium?

Clarke costs $1.50 per million input tokens and $7.00 per million output tokens. A five-turn conversation with one wiki search per turn, at about 61,250 input tokens and 2,250 output tokens, costs about $0.108. A company of 500 active users holding 3 conversations a working day would pay about $3,390 a month before prompt caching.

Does Radium support streaming and tool calling for copilots?

Yes. Streaming works in the OpenAI and Anthropic formats on all three models, including streamed tool call arguments. Tool calling supports parallel calls and strict schema validation on all three models, and multi-step tool loops on Hal and Clarke.

Can Radium cap AI spend per user or per team?

Not yet. Radium caps each response with max_tokens and exports per-request usage and cost from the dashboard, and budget alerts and limits are on its roadmap. Until then, meter usage per user in your own backend and enforce limits there.

Does Radium train on our internal documents and conversations?

No. Radium does not train on customer data, and prompts and completions are used only to service the request. Radium lists GDPR compliance, and SOC 2 Type II, ISO 27001 and HIPAA questions go through its security package.