How It Works
Understand the architecture behind MALV-based systems.
The Big Picture
A MALV-based system has three main parts:
- Apps - Microservices that expose tools
- Orchestrator - Discovers tools and coordinates execution
- Clients - Web or CLI interfaces where users interact
[IMAGE: Architecture diagram showing Apps, Orchestrator, and Clients as three connected components]
Apps
An app is a small, focused service. It does one thing well.
For example, you might have:
- A notes app that creates, edits, and lists notes
- An email app that sends and reads emails
- An auth app that handles login and permissions
Each app runs independently as a Cloudflare Worker (in production) or a local process (in development). Apps don't talk to each other directly. Instead, they expose tools that the orchestrator can discover and call.
Tools
Tools are the interface between AI and your code. Each tool is a function with:
- A name and description so the AI knows what it does
- An input schema defining what parameters it accepts
- An output schema defining what it returns
- Capabilities it needs (storage, tokens, etc.)
When you define a tool in tools.json, the orchestrator automatically learns about it. No registration code, no manual wiring.
The Orchestrator
The orchestrator is the brain. When a user sends a message, it:
- Discovers what tools are available
- Checks what the user is allowed to do (based on their tokens)
- Plans which tools to call and in what order
- Executes the tools with appropriate permissions
- Returns a response to the user
[IMAGE: Flow diagram showing message -> discover -> plan -> execute -> respond]
The orchestrator reads your tools.json files to understand what's possible. It uses AI to decide which tools match the user's intent, then calls them in sequence.
Tokens
Tokens represent permissions and state. They're signed JWTs that prove things like:
- "This user is logged in"
- "This user has connected their Gmail"
- "This user has selected project X"
Tools can require tokens. If a user doesn't have the right token, the tool won't be available to them. This keeps things secure without complex permission code.
Storage
Storage is where your data lives. It's permission-enforced, meaning:
- Apps can only access paths they've declared
- User data is isolated by user ID
- Team data is isolated by team ID
You define storage permissions in storage.json. The storage service checks these permissions on every request.
The Request Flow
Here's what happens when a user says "create a note called Meeting Notes":
- User sends message via web client
- Orchestrator receives the message
- Orchestrator discovers available tools (including
create_note) - Orchestrator plans to call
create_notewith title "Meeting Notes" - Notes app executes
create_note, saves to storage - Result returns through orchestrator to user
- User sees confirmation that the note was created
All the routing, permission checking, and coordination happens automatically based on your declarations.
Local Development
During development, everything runs locally:
- Apps run on localhost ports (4550, 4551, etc.)
- An infrastructure server provides token signing, storage, and search
- The CLI coordinates everything with
malv dev
malv dev
This starts all your apps and infrastructure. You can test the full flow without deploying anything.
Production
In production, apps deploy as Cloudflare Workers. Infrastructure services (tokens, storage, events) run as separate Workers with R2 storage.
The architecture stays the same - only the hosting changes.
Why This Architecture?
Declarative over imperative - You describe what's possible, not how to route requests.
Isolated microservices - Apps are independent. You can update one without touching others.
Automatic discovery - Add a tool to tools.json and it's immediately available.
Permission by default - Everything requires explicit permission declarations.
AI-native - The architecture is designed for AI to understand and navigate.