rw-integrate-characters
Help users create Runway Characters (GWM-1 avatars) and integrate real-time conversational sessions into their apps
What this skill does
# Integrate Characters (GWM-1 Avatars)
> **PREREQUISITES:**
> - `+rw-check-compatibility` — Project must have a server-side component (API key must NEVER be exposed to the client)
> - `+rw-fetch-api-reference` — Load the latest API reference from https://docs.dev.runwayml.com/api/ before integrating
> - `+rw-setup-api-key` — API credentials must be configured
>
> **OPTIONAL DEPENDENCIES:**
> - `+rw-integrate-documents` — Add a knowledge base to your character
> - `+rw-integrate-character-embed` — Use the React SDK to embed the avatar call UI
Help users create Runway Characters — real-time conversational AI avatars powered by GWM-1.
Use this only when modifying a user's codebase. For direct avatar management or other one-off Runway account actions from the agent, use `+use-runway-api` instead.
Characters are generated from a **single image** (any visual style — photorealistic, animated, non-human) with full control over voice, personality, knowledge, and actions. No fine-tuning or training required.
## Key Concepts
### Avatars vs Sessions
| Concept | Description |
|---------|-------------|
| **Avatar** | A persistent persona with a defined appearance, voice, and personality. Created once, used many times. |
| **Session** | A live WebRTC connection for real-time conversation. Connects one user to one avatar. **Max duration: 5 minutes.** |
### Session Lifecycle
```
┌───────────┐
┌──────────┤ NOT_READY ├──────────┐
│ └─────┬─────┘ │
│ │ │
▼ ▼ ▼
CANCELLED READY FAILED
┌──┴──┐
│ │
▼ ▼
RUNNING FAILED
┌──┴──┐
│ │
▼ ▼
COMPLETED CANCELLED
```
| Status | Description |
|--------|-------------|
| `NOT_READY` | Session is being provisioned. Poll until ready. |
| `READY` | Session is ready. The `sessionKey` is available. |
| `RUNNING` | WebRTC connection is active. Conversation in progress. |
| `COMPLETED` | Session ended normally. |
| `FAILED` | Error occurred. Check the `failure` field. |
| `CANCELLED` | Explicitly cancelled before completion. |
> **Important:** Session credentials can only be consumed **once**. If the WebRTC connection fails after credentials are consumed, you must create a new Session.
### Architecture
The API key must stay server-side. The flow is:
```
Client (React) → Your Server → Runway API
↓
Client (React) ←─── WebRTC ───← Runway (realtime)
```
1. Client requests a session from **your** server
2. Your server calls Runway API to create a session (`POST /v1/realtime_sessions`)
3. Your server polls until session is `READY` (`GET /v1/realtime_sessions/:id`)
4. Your server consumes credentials (`POST /v1/realtime_sessions/:id/consume`)
5. Your server returns credentials to the client
6. Client establishes a direct WebRTC connection to Runway
## Step 1: Install Dependencies
```bash
npm install @runwayml/sdk @runwayml/avatars-react
```
- `@runwayml/sdk` — Server-side SDK (session creation, avatar management)
- `@runwayml/avatars-react` — Client-side React components (WebRTC, UI)
## Step 2: Create an Avatar
Avatars can be created via the **Developer Portal** (UI) or the **API** (programmatic).
### Option A: Developer Portal (Recommended for first time)
1. Go to **https://dev.runwayml.com/** → **Characters** tab
2. Click **Create a Character**
3. Upload a reference image (tips below)
4. Choose a voice preset
5. Write personality instructions (e.g., "You are a helpful customer support agent for Acme Corp...")
6. Optionally add a starting script (what the character says first)
7. Optionally upload knowledge documents (`.txt` files)
8. Click **Create Character**
9. Copy the **Avatar ID** (a UUID like `8be4df61-93ca-11d2-aa0d-00e098032b8c`)
### Option B: API (Programmatic)
```javascript
// Node.js
import RunwayML from '@runwayml/sdk';
const client = new RunwayML();
const avatar = await client.avatars.create({
name: 'Support Agent',
referenceImage: 'https://example.com/avatar.png',
voice: {
type: 'runway-live-preset',
presetId: 'clara',
},
personality: 'You are a helpful customer support agent for Acme Corp. You help users with billing questions and technical issues.',
});
console.log('Avatar ID:', avatar.id);
```
```python
# Python
from runwayml import RunwayML
client = RunwayML()
avatar = client.avatars.create(
name='Support Agent',
reference_image='https://example.com/avatar.png',
voice={
'type': 'runway-live-preset',
'preset_id': 'clara',
},
personality='You are a helpful customer support agent for Acme Corp.',
)
print('Avatar ID:', avatar.id)
```
**If the reference image is a local file**, upload it first using `+rw-integrate-uploads`:
```javascript
import fs from 'fs';
const upload = await client.uploads.createEphemeral(
fs.createReadStream('/path/to/avatar-image.png')
);
const avatar = await client.avatars.create({
name: 'Support Agent',
referenceImage: upload.runwayUri,
voice: { type: 'runway-live-preset', presetId: 'clara' },
personality: 'You are a helpful customer support agent...',
});
```
### Reference Image (Required)
`referenceImage` is **required** when creating an avatar. It accepts three formats:
| Format | Limit | When to use |
|--------|-------|-------------|
| `https://…` URL | 2048 chars | Image already hosted publicly |
| `data:image/…;base64,…` | 5 MB (characters) | Small-to-medium local files (~3.5 MB raw max) |
| `runway://…` URI | 5000 chars | Large files uploaded via `/v1/uploads` first |
<<<<<<< HEAD:skills/rw-integrate-characters/SKILL.md
For local files over ~3.5 MB, use the upload flow (`+rw-integrate-uploads`) to get a `runway://` URI instead of a data URI.
=======
For local files over ~3.5 MB, use the upload flow (`+integrate-uploads`) to get a `runway://` URI instead of a data URI.
>>>>>>> 810dd3a (Improve CLI error details, auth fallback, and skill docs from testing):skills/integrate-characters/SKILL.md
### Reference Image Guidelines
- **Any visual style works**: photorealistic humans, animated mascots, stylized brand characters
- Use high-quality images with good lighting
- **Face must be clearly visible and centered** — images without a recognizable face will fail processing
- Avoid images with multiple people or obstructions
- Recommended aspect ratio: **1088×704**
### Voice Presets
| Preset ID | Name | Style |
|-----------|------|-------|
| `clara` | Clara | Soft, approachable |
| `victoria` | Victoria | Firm, professional |
| `vincent` | Vincent | Knowledgeable, authoritative |
Preview all voices in the [Developer Portal](https://dev.runwayml.com/).
## Step 3: Create a Session (Server-Side)
This is the **server-side API route** that your client will call. It creates a session, polls until ready, consumes credentials, and returns them.
### Next.js App Router
```typescript
// app/api/avatar/session/route.ts
import RunwayML from '@runwayml/sdk';
const client = new RunwayML();
export async function POST(request: Request) {
const { avatarId } = await request.json();
// 1. Create session
const { id: sessionId } = await client.realtimeSessions.create({
model: 'gwm1_avatars',
avatar: { type: 'custom', avatarId },
});
// 2. Poll until ready
let sessionKey: string | undefined;
for (let i = 0; i < 60; i++) {
const session = await client.realtimeSessions.retrieve(sessionId);
if (session.status === 'READY') {
sessionKey = session.sessionKey;
break;
}
if (session.status === 'FAILED') {
return Response.json({ error: session.failure }, { status: 500 });
}
await new Promise(r => setTimeout(r, 1000));
}
if (!sessionKey) {
return Response.json({ error: 'Session timedRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.