name: molykit
description: CRITICAL: Use for MolyKit AI chat toolkit. Triggers on: BotClient, OpenAI, SSE streaming, AI chat, molykit, PlatformSend, spawn(), ThreadToken, cross-platform async, Chat widget, Messages, PromptInput
category: AI & Agents
source: antigravity
tags: [markdown, api, mcp, ai, llm, gpt, design, image, aws, rag]
url: https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/molykit
MolyKit Skill
Best practices for building AI chat interfaces with Makepad using MolyKit - a toolkit for cross-platform AI chat applications.
Source codebase: /Users/zhangalex/Work/Projects/FW/robius/moly/moly-kit
When to Use
Use this skill when:
- Building AI chat interfaces with Makepad
- Integrating OpenAI or other LLM APIs
- Implementing cross-platform async for native and WASM
- Creating chat widgets (messages, prompts, avatars)
- Handling SSE streaming responses
- Keywords: molykit, moly-kit, ai chat, bot client, openai makepad, chat widget, sse streaming
Overview
MolyKit provides:
- Cross-platform async utilities (PlatformSend, spawn(), ThreadToken)
- Ready-to-use chat widgets (Chat, Messages, PromptInput, Avatar)
- BotClient trait for AI provider integration
- OpenAI-compatible client with SSE streaming
- Protocol types for messages, bots, and tool calls
- MCP (Model Context Protocol) support
Cross-Platform Async Patterns
PlatformSend - Send Only on Native
pub trait PlatformSend: PlatformSendInner {}
pub type BoxPlatformSendFuture<'a, T> = Pin<Box<dyn PlatformSendFuture<Output = T> + 'a>>;
pub type BoxPlatformSendStream<'a, T> = Pin<Box<dyn PlatformSendStream<Item = T> + 'a>>;
Platform-Agnostic Spawning
pub fn spawn(fut: impl PlatformSendFuture<Output = ()> + 'static);
spawn(async move {
let result = fetch_data().await;
Cx::post_action(DataReady(result));
SignalToUI::set_ui_signal();
});
Task Cancellation with AbortOnDropHandle
pub struct AbortOnDropHandle(AbortHandle);
#[rust]
task_handle: Option<AbortOnDropHandle>,
fn start_task(&mut self) {
let (future, handle) = abort_on_drop(async move {
});
self.task_handle = Some(handle);
spawn(async move { let _ = future.await; });
}
ThreadToken for Non-Send Types on WASM
pub struct ThreadToken<T: 'static>;
impl<T> ThreadToken<T> {
pub fn new(value: T) -> Self;
pub fn peek<R>(&self, f: impl FnOnce(&T) -> R) -> R;
pub fn peek_mut<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
}
let token = ThreadToken::new(non_send_value);
spawn(async move {
token.peek(|value| {
});
});
BotClient Trait
Implementing AI Provider Integration
pub trait BotClient: Send {
fn send(
&mut self,
bot_id: &BotId,
messages: &[Message],
tools: &[Tool],
) -> BoxPlatformSendStream<'static, ClientResult<MessageContent>>;
fn bots(&self) -> BoxPlatformSendFuture<'static, ClientResult<Vec<Bot>>>;
fn clone_box(&self) -> Box<dyn BotClient>;
}
let client = OpenAIClient::new("https://api.openai.com/v1".into());
client.set_key("sk-...")?;
let context = BotContext::from(client);
BotContext - Sharable Wrapper
pub struct BotContext(Arc<Mutex<InnerBotContext>>);
impl BotContext {
pub fn load(&mut self) -> BoxPlatformSendFuture<ClientResult<()>>;
pub fn bots(&self) -> Vec<Bot>;
pub fn get_bot(&self, id: &BotId) -> Option<Bot>;
pub fn client(&self) -> Box<dyn BotClient>;
}
let mut context = BotContext::from(client);
spawn(async move {
if let Err(errors) = context.load().await.into_result() {
}
Cx::post_action(BotsLoaded);
});
Protocol Types
Message Structure
pub struct Message {
pub from: EntityId,
pub metadata: MessageMetadata,
pub content: MessageContent,
}
pub struct MessageContent {
pub text: String,
pub reasoning: String,
pub citations: Vec<String>,
pub attachments: Vec<Attachment>,
pub tool_calls: Vec<ToolCall>,
pub tool_results: Vec<ToolResult>,
}
pub struct MessageMetadata {
pub is_writing: bool,
pub created_at: DateTime<Utc>,
}
Bot Identification
pub struct BotId(Arc<str>);
impl BotId {
pub fn new(id: &str, provider: &str) -> Self;
pub fn id(&self) -> &str;
pub fn provider