| Crates.io | umf |
| lib.rs | umf |
| version | 0.1.4 |
| created_at | 2025-10-30 14:31:05.308989+00 |
| updated_at | 2025-12-10 11:54:08.07935+00 |
| description | Universal Message Format (UMF) - Provider-agnostic message representation for LLM interactions with ChatML formatting support |
| homepage | https://umf.podtan.com |
| repository | https://github.com/podtan/umf |
| max_upload_size | |
| id | 1908310 |
| size | 109,750 |
A provider-agnostic message representation for LLM (Large Language Model) interactions.
UMF provides a standardized message format that can be converted to any LLM provider format (OpenAI, Anthropic, Google Gemini, Cohere, etc.). It follows OpenAI's JSON structure as the foundation while supporting flexible conversion to provider-specific formats.
Add to your Cargo.toml:
[dependencies]
umf = "0.1.0"
use umf::{InternalMessage, MessageRole, ContentBlock};
// Create a simple text message
let msg = InternalMessage::user("Hello, world!");
// Create a message with tool calls
let msg = InternalMessage::assistant_with_tools(
"Let me search for that",
vec![ContentBlock::tool_use(
"call_123",
"search",
serde_json::json!({"query": "rust programming"}),
)],
);
// Create a tool result message
let msg = InternalMessage::tool_result(
"call_123",
"search",
"Found 5 results about rust programming",
);
pub struct InternalMessage {
pub role: MessageRole, // system, user, assistant, tool
pub content: MessageContent, // Text or Blocks
pub metadata: HashMap<String, String>,
pub tool_call_id: Option<String>, // For tool messages
pub name: Option<String>, // For tool messages
}
Simple Text:
let msg = InternalMessage::user("Hello");
Structured Content Blocks:
use umf::ContentBlock;
let blocks = vec![
ContentBlock::text("I'll help you with that"),
ContentBlock::tool_use("call_123", "search", serde_json::json!({"q": "test"})),
];
let msg = InternalMessage {
role: MessageRole::Assistant,
content: MessageContent::Blocks(blocks),
// ...
};
Tool Use:
let tool_call = ContentBlock::tool_use(
"call_abc123",
"search",
serde_json::json!({"query": "weather"}),
);
Tool Result:
let msg = InternalMessage::tool_result(
"call_abc123",
"search",
"It's sunny, 72°F",
);
UMF types serialize to JSON exactly as specified:
Text Block:
{
"type": "text",
"text": "Hello world"
}
Tool Use Block:
{
"type": "tool_use",
"id": "call_123",
"name": "search",
"input": {"query": "weather"}
}
Tool Result Block:
{
"type": "tool_result",
"tool_use_id": "call_123",
"content": "Result text"
}
UMF can be converted to any provider format:
role, content, tool_calls as-istool_calls to content blocksrole: "tool" to role: "user" with tool_result blocksUMF follows the Universal Message Format specification:
type field ("text", "tool_use", "tool_result")data objects)Run tests:
cargo test -p umf
All tests include:
MIT OR Apache-2.0
specs/universal-message-format/