Quickstart Guide
This guide walks you through creating your first MFP agents, establishing a secure channel, and exchanging messages.
Prerequisites
Section titled “Prerequisites”- Python 3.11+
- MFP installed:
pip install mfp
Step 1: Create a Runtime
Section titled “Step 1: Create a Runtime”Every MFP application starts with a Runtime:
from mfp import Runtime, RuntimeConfig
# Create runtime configurationconfig = RuntimeConfig()
# Initialize the runtimeruntime = Runtime(config)The Runtime manages agent lifecycles, message routing, and cryptographic operations.
Step 2: Define Agent Callables
Section titled “Step 2: Define Agent Callables”Agents are Python callables that receive and process messages:
def alice(channel_id, message): """Alice's message handler.""" print(f"[Alice] Received on {channel_id.hex()[:8]}: {message.decode()}") return {"status": "received", "agent": "alice"}
def bob(channel_id, message): """Bob's message handler.""" print(f"[Bob] Received on {channel_id.hex()[:8]}: {message.decode()}") return {"status": "received", "agent": "bob"}Signature: (channel_id: bytes, message: bytes) -> dict
The return value is metadata that can be used for logging, debugging, or hook integration.
Step 3: Bind Agents to the Runtime
Section titled “Step 3: Bind Agents to the Runtime”Binding registers an agent with the runtime and assigns it a unique AgentId:
from mfp import bind
# Bind agentsalice_handle = bind(runtime, alice)bob_handle = bind(runtime, bob)
print(f"Alice ID: {alice_handle.agent_id.hex()[:16]}...")print(f"Bob ID: {bob_handle.agent_id.hex()[:16]}...")AgentHandle provides the interface for all agent operations: establishing channels, sending messages, querying status.
Step 4: Establish a Channel
Section titled “Step 4: Establish a Channel”Create an encrypted channel between Alice and Bob:
# Alice initiates a channel to Bobalice_handle.establish_channel( peer_id=bob_handle.agent_id, symmetric_key=None # Auto-generate a secure key)
print("Channel established!")When symmetric_key=None, MFP generates a 32-byte ChaCha20-Poly1305 key automatically.
Step 5: Send Messages
Section titled “Step 5: Send Messages”Use the mfp_send tool to send encrypted messages:
from mfp import mfp_send, mfp_channels
# Get Alice's channelschannels = mfp_channels(alice_handle)channel = channels[0]
print(f"Channel ID: {channel.channel_id.hex()[:16]}...")print(f"Peer: {channel.peer_id.hex()[:16]}...")
# Alice sends to Bobreceipt = mfp_send( alice_handle, channel_id=channel.channel_id, plaintext=b"Hello Bob, this is Alice!")
print(f"Message sent! Receipt: {receipt.message_id.hex()[:16]}...")Receipt contains:
message_id: unique message identifiersequence_number: monotonic counter for orderingtimestamp_ns: nanosecond-precision timestamp
Step 6: Query Agent Status
Section titled “Step 6: Query Agent Status”Check agent state at any time:
from mfp import mfp_status
# Get Alice's statusstatus = mfp_status(alice_handle)
print(f"Agent state: {status.state}") # AgentStatus.ACTIVEprint(f"Channels: {status.channel_count}")print(f"Pending messages: {status.pending_message_count}")AgentStatus states:
BOUND— registered, no channels yetACTIVE— has at least one channelQUARANTINED— isolated due to errorsUNBOUND— deregistered
Step 7: Two-Way Communication
Section titled “Step 7: Two-Way Communication”Bob can send back to Alice on the same channel:
# Bob gets his channels (same channel, from his perspective)bob_channels = mfp_channels(bob_handle)bob_channel = bob_channels[0]
# Bob repliesreply_receipt = mfp_send( bob_handle, channel_id=bob_channel.channel_id, plaintext=b"Hi Alice! Message received.")
print(f"Reply sent: {reply_receipt.message_id.hex()[:16]}...")Both Alice and Bob share the same ChannelId, ensuring symmetric communication.
Step 8: Shutdown
Section titled “Step 8: Shutdown”Clean up when done:
from mfp import unbind
# Unbind agents (closes channels, flushes state)unbind(alice_handle)unbind(bob_handle)
# Shutdown the runtimeruntime.shutdown()
print("Runtime shut down cleanly.")Complete Example
Section titled “Complete Example”from mfp import ( Runtime, RuntimeConfig, bind, unbind, mfp_send, mfp_channels, mfp_status)
# Agent callablesdef alice(channel_id, message): print(f"[Alice] {message.decode()}") return {"status": "ok"}
def bob(channel_id, message): print(f"[Bob] {message.decode()}") return {"status": "ok"}
# Initializeconfig = RuntimeConfig()runtime = Runtime(config)
# Bindalice_handle = bind(runtime, alice)bob_handle = bind(runtime, bob)
# Establish channelalice_handle.establish_channel(bob_handle.agent_id, symmetric_key=None)
# Send messagechannels = mfp_channels(alice_handle)receipt = mfp_send( alice_handle, channel_id=channels[0].channel_id, plaintext=b"Hello from Alice!")
print(f"Sent: {receipt.message_id.hex()[:16]}...")
# Cleanupunbind(alice_handle)unbind(bob_handle)runtime.shutdown()Next Steps
Section titled “Next Steps”- API Reference — explore the full library interface
- Server Guide — run MFP as a standalone process
- Architecture — understand the internal design
- Security Model — learn about MFP’s security guarantees
Tip: For production use, persist agent state using the StorageEngine and configure federation via TransportServer. See the Server Guide for details.