Quickstart
Add a Model
Register a model with AIChannel and AIService.
Create an AIChannel, implement its Downcity Model Protocol stream, then register an AIModelSpec:
import {
AIChannel,
AIService,
stream_openai_compatible_model,
type AIChannelStreamInput,
type AIChannelStreamResult,
} from "@downcity/federation";
class DeepSeekChannel extends AIChannel {
constructor() {
super({
id: "deepseek",
env: { DEEPSEEK_API_KEY: "DeepSeek API Key" },
base_url: "https://api.deepseek.com/v1",
});
}
protected async stream(
input: AIChannelStreamInput,
): Promise<AIChannelStreamResult> {
const api_key = input.env("DEEPSEEK_API_KEY");
if (!api_key) throw new Error("DEEPSEEK_API_KEY is required");
return stream_openai_compatible_model(input, {
api_key,
base_url: this.base_url ?? "https://api.deepseek.com/v1",
});
}
}
const channel = new DeepSeekChannel();
const ai = new AIService();
ai.use(channel.model({
id: "deepseek-v4-flash",
upstream_model: "deepseek-chat",
name: "DeepSeek V4 Flash",
context_window: 128_000,
}));
federation.use(ai);This single stream() implementation powers city.ai.stream(), CityModel, and /v1/ai/chat/completions.
See AIChannel and model registration for reasoning, fallback, billing, and provider_options.