Cosmo Realtime SDK
Capabilities

Skills

SKILL.md playbooks loaded just-in-time — keep the prompt small and the expertise on demand.

Skills solve a prompt-budget problem. A capable agent might need ten detailed procedures — card activation, refund flow, escalation script — but stuffing all ten into the instructions bloats every turn and dilutes the persona. A skill keeps only its name and one-line description resident in the prompt (the menu); the full body loads just-in-time when the conversation actually goes there.

Skills follow the Agent Skills standard: a SKILL.md document with frontmatter (name, description) and a markdown body. They never appear on the wire as a separate concept — the SDK compiles them into an instructions suffix (the menu) plus one cosmo_sdk_load_skill client tool. When the model recognizes it needs a skill, it calls cosmo_sdk_load_skill, receives the body as the tool result, and the procedure stays in context for the rest of the call.

That changes how an agent scales. Instructions are resident context, re-read on every turn of every session, so a prompt that grows with each new procedure raises the cost of every turn — and long prompts dilute themselves, each rule competing with more neighbors for the model's attention. A skill adds one menu line to that resident cost; the body is paid for only in the sessions that go there. Ten procedures or forty, the prompt the model sees on an ordinary turn stays the same size, so one agent keeps absorbing tasks without its per-turn cost climbing or its instruction-following degrading.

Attach skills

import { parseSkillMd } from 'cosmo-ai';

const skillText = await fetch('/skills/card-activation.md').then(r => r.text());
const agent = client.agent({
  instructions: '…',
  skills: [parseSkillMd(skillText, 'card-activation')],
});
from pathlib import Path
from cosmo_ai import RealtimeClient

client = RealtimeClient(api_key=os.environ["COSMO_API_KEY"])
agent = client.agent(
    instructions="You are Alex at Acme.",
    skills=Path("./skills"),          # each subdirectory holds a SKILL.md
)
from cosmo_ai.skills import Skill

card_activation = Skill(
    name="card-activation",
    description="Walk a customer through activating a new card.",
    body=CARD_ACTIVATION_PLAYBOOK,
)
agent = client.agent(instructions="…", skills=[card_activation])
from cosmo_ai.skills import parse_skill_md

# SKILL.md text that never touches a local directory — fetched, or read
# out of a database.
card_activation = parse_skill_md(skill_text, default_name="card-activation")
agent = client.agent(instructions="…", skills=[card_activation])

.directory(_:) reads a directory of SKILL.md files; parseSkillMd(_:defaultName:) parses one you already hold.

import CosmoRealtime

let agent = try client.agent(skills: .directory(skillsURL))
let session = try await agent.start()
let cardActivation = try parseSkillMd(skillText, defaultName: "card-activation")
let agent = try client.agent(instructions: "…", skills: [cardActivation])

Malformed documents (missing frontmatter, missing required fields) and duplicate skill names fail when the agent is built — SkillError in every SDK, with a code naming the failure — not mid-call. That is deliberate: a bad playbook is a deployment error you want at startup, not a tool call that quietly returns nothing halfway through a customer conversation.

Write a good skill

---
name: card-activation
description: Walk a customer through activating a new card.
---

## Steps
1. Confirm the last four digits of the card.
2. …
  • The description is the routing signal — it's all the model sees before deciding to load. Write it like a when-to-use line, not a title.
  • The body is a procedure the model follows once loaded. Keep it imperative and self-contained.
  • Once loaded, a skill stays in context for the rest of the session and never unloads.

Choose between skills, instructions, and tools

The following table shows which mechanism suits each kind of content.

Put it in…When
instructionsidentity, tone, always-on rules — read on every turn
a skilla detailed procedure needed only in some conversations
a toolan action with side effects — skills inform, tools act

Skill loads are ordinary tool calls, so they show up in the tool-call / tool-result event stream and can be observed (or even denied) with hooks matching cosmo_sdk_load_skill.

On this page