Quickstart

Try It Now

Run a complete call chain with Federation and Embassy.

1. Start City

import {
  Federation,
  AIService,
  AIChannel,
  type AIChannelStreamInput,
  type AIChannelStreamResult,
} from "@downcity/federation";
import { Database } from "@downcity/database-sqlite";

const database = new Database({ filename: "./data.sqlite" });
const base = new Federation({ database });

class EchoChannel extends AIChannel {
  constructor() {
    super({ id: "echo" });
  }

  protected async stream(
    input: AIChannelStreamInput,
  ): Promise<AIChannelStreamResult> {
    const input_text = input.call.messages
      .flatMap((message) => message.content)
      .filter((part) => part.type === "text")
      .map((part) => part.text)
      .join("\n");
    return {
      stream: new ReadableStream({
        start(controller) {
          controller.enqueue({ type: "model_start", request_id: crypto.randomUUID(), model_id: input.model.id });
          controller.enqueue({ type: "text_start", content_id: "echo_text" });
          controller.enqueue({ type: "text_delta", content_id: "echo_text", delta: `Echo: ${input_text}` });
          controller.enqueue({ type: "text_finish", content_id: "echo_text" });
          controller.enqueue({
            type: "model_usage",
            usage: { input_tokens: 0, output_tokens: 0, total_tokens: 0 },
          });
          controller.enqueue({ type: "model_finish", finish_reason: "stop" });
          controller.close();
        },
      }),
    };
  }
}

const echo = new EchoChannel();

const ai = new AIService();
ai.use(echo.model({ id: "local-echo", upstream_model: "local-echo", name: "Local Echo" }));
base.use(ai);

await base.health();
serve({ fetch: (request) => base.fetch(request), port: 43127, hostname: "127.0.0.1" });

2. Create Bureau & Request Token

import { Embassy } from "@downcity/federation";

const embassy = new Embassy({
  federation_url: "http://127.0.0.1:43127",
  admin_token: administrator_session_token,
});
const token = await embassy.admin.service("accounts").action("tokens/issue").invoke({
  bureau_id: "demo",
  user_id: "user_123",
  ttl: "7d",
});

3. Client Call

const user_embassy = new Embassy({
  federation_url: "http://127.0.0.1:43127",
  user_token: token.user_token,
});

const catalog = await user_embassy.user.ai.catalog();
const model = catalog.require("local-echo");

// SDK pathway
const stream = await model.stream({
  messages: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
});
for await (const event of stream) {
  if (event.type === "text_delta") process.stdout.write(event.delta);
}

Next Steps