Skip to main content

MIA — Map of Intent and Action. A framework for mapping natural language into structured, executable actions for AI agents.

Project description

MIA

Map of Intent and Action

A framework for mapping natural language into structured, executable actions.
Built for AI agents that need to understand what users mean — not just what they say.

The Problem · The Solution · How It Works · Quick Start · Using MIA as RAG · Architecture Patterns · Production Guide · License


The Problem

You're building an AI agent that converts natural language into actions — SQL queries, API calls, tool executions. The user asks:

"How much did I sell yesterday?"

Sounds simple. But:

  • "I" — is this a salesperson asking about their sales? A manager asking about their store? A director asking about the region?
  • "sell" — which table? sales? orders? transactions? receipts?
  • "yesterday"CURRENT_DATE - 1? What about timezone?

Now multiply this by hundreds of possible questions, business jargon that no LLM knows, and domain-specific logic that lives only in people's heads.

This is the gap MIA fills.

The Solution

MIA (Map of Intent and Action) is a structured framework that decomposes ambiguous natural language into executable actions through four columns:

Question Intent Operation Action
What the user said What they actually meant How to solve it What to execute

Each column progressively removes ambiguity:

"How much did I sell yesterday?"
        ↓
"Total store revenue for the previous day"        ← Intent (disambiguated)
        ↓
"Sum of sales values filtered by date = yesterday" ← Operation (logic)
        ↓
SQL: SELECT SUM(amount) FROM sales WHERE date = CURRENT_DATE - 1  ← Action (executable)

MIA captures what schemas can't

Business domains are full of implicit knowledge. In a supermarket, "How many customers did I have?" doesn't mean counting rows in a customers table — it means counting receipts issued. No database schema tells you that. No LLM knows that. But MIA does:

Question Intent Operation Action
How many customers did I have yesterday? Number of receipts issued yesterday Count of receipts filtered by date = yesterday SELECT COUNT(*) FROM receipts WHERE date = CURRENT_DATE - 1

How It Works

A MIA file is an Excel spreadsheet with two sheets:

Sheet 1: Identity

Metadata that defines the scope of this MIA.

Field Description
Name Unique identifier (e.g., "MIA Sales")
Domain Business area covered (e.g., "Sales Module")
Data Source Where the agent executes actions (e.g., "PostgreSQL sales_db")
Agent Which agent consumes this MIA (e.g., "sales-agent-v1")
Version Document evolution control
Description One-line scope summary

Sheet 2: Map

The core table. Four columns, always the same — regardless of whether it's an orchestrator, a specialist agent, or a monolith.

Examples across different action types:

Question Intent Operation Action
How much did I sell yesterday? Total store revenue yesterday Sum of sales filtered by date SQL: SELECT SUM(amount) FROM sales WHERE date = CURRENT_DATE - 1
What's the status of my order? Track current order status Lookup order by user ID via logistics API API: GET /api/v1/tracking/{order_id}
Let the team know the report is ready Send notification about report completion Identify team channel and compose message Tool: send_slack_message(channel='#sales', text='Report ready')
I need a report on sales and inventory Generate cross-domain report Identify domains: Sales + Inventory Route -> Sales Agent + Inventory Agent

Same question, different profiles

When user profiles change behavior, duplicate the row — the Intent naturally differentiates:

Question Intent Operation Action
How much did I sell yesterday? Store revenue yesterday Sum filtered by store and date ...WHERE store_id = @store
How much did I sell yesterday? Salesperson revenue yesterday Sum filtered by salesperson and date ...WHERE salesperson_id = @user

No extra columns. No conditional logic. Clean rows, each self-contained.

Quick Start

Prerequisites

  • Python 3.10+

Install

git clone https://github.com/otavioturatti/mia-framework.git
cd mia-framework
pip install -e .

This installs the mia package and two CLI commands: mia-generate and mia-export. For development, use pip install -e ".[dev]" to include pytest.

1. Generate the template

mia-generate

This creates MIA_Template.xlsx — a styled spreadsheet with examples and empty rows ready to fill.

2. Fill in your MIA

Open the Excel file and:

  1. Fill the Identity sheet with your project metadata
  2. Fill the Map sheet with your question-intent-operation-action rows

3. Export to JSON

mia-export examples/MIA_Template.xlsx

This generates a MIA_Template_export.json where each row becomes a structured document:

{
  "id": "mia_sales_001",
  "content_for_embedding": "How much did I sell yesterday? — Total store revenue for the previous day",
  "content_for_reranking": "Total store revenue for the previous day — Sum of sales values filtered by date = yesterday",
  "metadata": {
    "question": "How much did I sell yesterday?",
    "intent": "Total store revenue for the previous day",
    "operation": "Sum of sales values filtered by date = yesterday",
    "action": "SQL: SELECT SUM(amount) FROM sales WHERE date = CURRENT_DATE - 1",
    "domain": "Sales",
    "version": "1.0"
  }
}

Two embedding fields by design:

  • content_for_embeddingQuestion + Intent for primary vector search (richer semantic surface than question alone)
  • content_for_rerankingIntent + Operation for cross-encoder reranking (captures the "what" and "how")

## Using MIA as RAG

MIA is designed to be consumed in three ways:

### 1. Design document
Fill the MIA **before** building the agent. It forces you to think through every intent, every edge case, every piece of business jargon.

### 2. Few-shot examples
Feed MIA rows directly into the agent's prompt as examples of how to map questions to actions.

### 3. RAG knowledge base
Embed the MIA and let the agent **search for similar questions at runtime**:

User asks: "What were my sales last week?" ↓ Semantic search on MIA embeddings ↓ Closest match: "How much did I sell yesterday?" ↓ Agent reads: Intent + Operation + Action ↓ Adapts the pattern to generate the correct response


The `content_for_embedding` field contains the **Question + Intent** — this is what gets vectorized. Including Intent means that duplicate questions with different profiles (e.g., "store revenue" vs. "salesperson revenue") produce **different vectors**. The rest comes back as **metadata** after retrieval.

### Why this works

You don't need to list every possible phrasing. RAG works by **semantic similarity**, not exact matching:

- "how much did I sell yesterday" 
- "what was yesterday's revenue"
- "yesterdays sales total"
- "hwat did i sel yestrday" *(typos included)*

All of these land close to the same embedding vector. **One representative question per intent is enough.**

## Architecture Patterns

### Monolith — Single MIA

One agent, one database, one MIA. Simple.

User Question → MIA (RAG) → Agent → Database


### Microservices — One MIA per domain

Each service has its own agent, its own data, and its own MIA. The MIA defines the "world" each agent can see.

User Question → Orchestrator MIA → Routes to domain ↓ ┌───────────────────────┐ │ Sales MIA → Sales DB │ │ Stock MIA → Stock DB │ │ HR MIA → HR System │ └───────────────────────┘


The orchestrator itself uses a MIA — its Actions are **routing decisions**, not SQL or API calls.

### The framework is role-agnostic

The four columns stay the same whether you're building an orchestrator or a specialist. What changes is what you write in the **Action** column:

| Role | Action column contains |
|------|----------------------|
| Specialist agent | SQL queries, API calls, tool executions |
| Orchestrator | Routing decisions (`Route -> Agent X`) |

Same framework. Same table. The intelligence is in how you fill it — not in the structure.

## Tips for filling a great MIA

- **One representative question per intent.** Don't list variations — RAG handles semantic similarity.
- **Capture business jargon in the Intent column.** This is where "customers" becomes "receipts issued" and "revenue" becomes `SUM(amount) FROM sales`.
- **Duplicate rows only when profiles change behavior.** If the question "How much did I sell?" means different things to a manager vs. a salesperson, create two rows.
- **The person filling the MIA should know the business.** This isn't a dev task — it's a domain expert task (or both working together).
- **Start small, grow organically.** Begin with the 20 most common questions. The MIA grows as the agent encounters new patterns.

## Production Guide

MIA is a **knowledge authoring framework** — it structures and exports your domain knowledge. The embedding, indexing, retrieval, and generation steps are the responsibility of your pipeline. This section covers how to integrate MIA exports into a production RAG system.

### Retrieval strategy

Use **hybrid search** (vector + keyword) for best results. Pure vector search can miss domain-specific jargon, acronyms, and technical terms that keyword matching handles well.

User query ↓ ┌──────────────────────────┐ │ Vector search (top 20) │ ← uses content_for_embedding │ + BM25 keyword (top 20) │ ← uses metadata.question └──────────────────────────┘ ↓ merge + deduplicate ┌──────────────────────────┐ │ Cross-encoder reranker │ ← uses content_for_reranking └──────────────────────────┘ ↓ top 3-5 Agent receives context


### Metadata filtering

When the same question maps to different actions per user profile, **filter by metadata at query time** — don't rely on embedding distance alone:

```python
results = vector_store.search(
    query_vector=embed(user_query),
    filters={"domain": "sales", "agent": "sales-agent-v1"},
    limit=10,
)

The metadata.domain, metadata.agent, and metadata.data_source fields exist for this purpose.

Confidence threshold and fallback

Not every user question will have a match in the MIA. Define a minimum similarity threshold and a fallback strategy:

SIMILARITY_THRESHOLD = 0.75  # tune for your domain

results = search(user_query)
if not results or results[0].score < SIMILARITY_THRESHOLD:
    return "I'm not sure I understand. Could you rephrase your question?"

In production, ~30-40% of queries may not have a direct match. Plan for it.

Note: Similarity thresholds vary drastically between embedding models. A score of 0.75 with text-embedding-3-large means something completely different than 0.75 with BGE-M3. Always calibrate your threshold against a test set of known question-intent pairs from your specific MIA and model combination.

Action safety

The action field in MIA contains templates, not executable code. Never interpolate user input directly into action strings. Always:

  • Use parameterized queries for SQL (WHERE id = $1, not string formatting)
  • Validate and sanitize any dynamic values before execution
  • Enforce role-based access control at the execution layer — the MIA defines what actions exist, not who can run them

Feedback loop

A MIA is a living document that improves over time. Track these metrics:

  • Unmatched queries — questions with no results above threshold (candidates for new MIA rows)
  • Retrieval quality — Recall@K, MRR on a test set of known question-intent pairs
  • Action success rate — did the generated action actually work?

Periodically review unmatched queries and add new rows to the MIA. The more rows, the smarter the agent.

Scaling beyond Excel

Excel works well up to ~500 rows. Beyond that, consider:

  • CSV/TSV as primary format, imported into the Excel template for review
  • Database-backed MIA with an export step to JSON
  • Multiple MIA files split by domain (the microservices pattern)

The export.py module works with any .xlsx that follows the MIA structure, regardless of how it was created.

Project Structure

mia-framework/
├── README.md                ← You are here
├── LICENSE                  ← MIT License
├── pyproject.toml           ← Dependencies, metadata, CLI entry points
├── src/mia/                 ← Installable Python package
│   ├── __init__.py
│   ├── exceptions.py        ← Custom MiaError exception
│   ├── generate_template.py ← Generates the Excel template (mia-generate)
│   └── export.py            ← Exports Excel → structured JSON (mia-export)
├── tests/                   ← Unit tests (pytest)
│   ├── test_generate_template.py
│   └── test_export.py
├── .github/workflows/
│   └── ci.yml               ← GitHub Actions CI
└── examples/
    └── MIA_Template.xlsx    ← Ready-to-use template with examples

License

MIT License — do whatever you want with it, just keep the attribution.


Created with love by Joao Otavio Turatti Barbosa

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mia_framework-1.1.1.tar.gz (23.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mia_framework-1.1.1-py3-none-any.whl (16.4 kB view details)

Uploaded Python 3

File details

Details for the file mia_framework-1.1.1.tar.gz.

File metadata

  • Download URL: mia_framework-1.1.1.tar.gz
  • Upload date:
  • Size: 23.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for mia_framework-1.1.1.tar.gz
Algorithm Hash digest
SHA256 cb160cc6bbc3bca4f09414af6eb7953cb98b82638db7983332ffc525ec84a7ea
MD5 b29a7f989e068d7defdff6eea2dc89ca
BLAKE2b-256 e90cb1ae360a1fea3300be32fe18e8313c83846e1782182a3ab33edd57aaacf5

See more details on using hashes here.

File details

Details for the file mia_framework-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: mia_framework-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 16.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for mia_framework-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9d54c76601921d91b39167819e518c20c1dd6d166f6434fa94357f044608fa4a
MD5 24f4b542df0ca02af611cc963984bb83
BLAKE2b-256 a35dd4bb29cc7a014870b20a81bcfae8064f4f995731eab0d2efaed27878c5d3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page