> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meibel.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Execution Policies

> How Meibel controls what data and tools an agent session can access at runtime through composable, platform-enforced constraints

## Overview

Conventional LLM guardrails operate through prompting, which means they can be bypassed through prompt injection or jailbreaking. Execution policies are **hardrails**: constraints enforced by the platform infrastructure itself, outside the LLM's execution path. The LLM cannot see, modify, or circumvent the authorization logic that drives an execution policy. Where a guardrail asks the model to comply, a hardrail makes non-compliance structurally impossible.

An execution policy narrows what data and tools are available to an agent session. It cannot make new datasources or tools available; it can only restrict access within what the agent is already configured to use. An execution policy has two sections: **datasource constraints**, which control access to the data the agent queries and retrieves, and **tool constraints**, which control which tools are available and what parameter values they accept.

The central use case is per-user data scoping in a multi-tenant environment. A single agent can serve many users, each with different data access permissions. Rather than building separate agents for each user, you define one agent and apply different execution policies when creating each user's session. One policy might restrict a session to European customer data; another might restrict it to a single client's documents. The agent configuration stays the same, and the policy controls what each session can see.

```json theme={null}
{
  "datasources": {
    "ds_abc123": {
      "tables": {
        "filter": {
          "table.__name__": { "$in": ["orders", "customers"] },
          "orders.region": "EU"
        },
        "hidden_columns": {
          "customers": ["ssn", "credit_card"]
        }
      },
      "documents": {
        "filter": {
          "data_element.__id__": { "$in": ["de_abc", "de_def"] }
        }
      }
    }
  },
  "tools": {
    "send_email": {
      "variables": {
        "to": "support@acme.com",
        "max_attachments": { "$lte": 3 }
      }
    },
    "web_search": { "disabled": true }
  }
}
```

This policy narrows the session to two tables in the EU region, hides sensitive columns from query results, limits document retrieval to two specific data elements, locks the email recipient, caps attachments, and removes web search entirely.

## Datasource constraints

Each entry in the `datasources` section is keyed by datasource ID and controls what the session can access within that datasource. A datasource can be disabled entirely by setting `disabled` to `true`, which blocks all queries against it.

For datasources that remain enabled, constraints are split into two categories that match the two ways an agent accesses data: table queries and document retrieval.

### Table constraints

Table constraints scope the SQL queries an agent can run against a datasource's structured data. They have three parts.

**Filters** narrow which tables and rows are accessible. Filter keys follow the format `table.column` for row-level scoping or use the built-in `table.__name__` field for table-level scoping. Values use constraint operators: comparison operators (`$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`), set operators (`$in`, `$nin`), and logical operators (`$and`, `$or`, `$not`).

```json theme={null}
{
  "filter": {
    "table.__name__": { "$in": ["orders", "customers"] },
    "orders.region": { "$eq": "EU" },
    "orders.amount": { "$gte": 100 }
  }
}
```

This filter restricts the session to the `orders` and `customers` tables, and within `orders`, only rows where `region` is `EU` and `amount` is at least 100. The platform enforces these constraints transparently, so the agent only ever sees rows that match.

Plain values are a shorthand for `$eq`: writing `"orders.region": "EU"` is equivalent to `"orders.region": { "$eq": "EU" }`.

**Hidden columns** remove specific column values from query results. The columns remain usable in WHERE and JOIN clauses, so the agent can filter on them and use them in joins, but their values are stripped from the output.

```json theme={null}
{
  "hidden_columns": {
    "customers": ["ssn", "credit_card"]
  }
}
```

**Hidden tables** work the same way at the table level: the table's columns are fully redacted from query output, but the table remains available for use in joins.

### Document constraints

Document constraints scope which documents the agent can retrieve through vector search. Their filter uses the same operator syntax as table constraints, with built-in fields for document identity:

* `data_element.__id__` scopes by data element ID
* `data_element.__name__` scopes by original filename

Custom indexed metadata fields configured on the datasource are also supported. In the example below, `product_line` is a custom metadata field:

```json theme={null}
{
  "filter": {
    "data_element.__id__": { "$in": ["de_abc", "de_def"] },
    "product_line": "commercial"
  }
}
```

The platform applies document filters to every vector search query. Documents that do not match are invisible to the agent.

## Tool constraints

Each entry in the `tools` section is keyed by tool instance name and controls how the session can use that tool. A tool can be disabled entirely by setting `disabled` to `true`, which removes it from the agent's available toolkit.

For tools that remain enabled, the `variables` field constrains parameter values. Constraints come in two forms that behave differently.

**Fixed values** are plain values (or `$eq` constraints). They constrain a parameter to a single allowed value. The platform annotates the tool's parameter description so the agent sees the constraint (e.g., "must equal '[support@acme.com](mailto:support@acme.com)'"), and validates at execution time that the agent provides the correct value.

```json theme={null}
{
  "send_email": {
    "variables": {
      "to": "support@acme.com"
    }
  }
}
```

Here, the agent sees that the `to` parameter must equal `support@acme.com`. If it provides any other value, the platform rejects the call.

**Range constraints** use operators like `$lte`, `$in`, or `$contains`. They work the same way: the parameter description is annotated with the constraint, and the platform validates the agent's value at execution time.

```json theme={null}
{
  "web_search": {
    "variables": {
      "query": { "$contains": "site:acme.com" },
      "count": { "$lte": 10 }
    }
  }
}
```

The agent can set `query` and `count`, but the platform rejects any search query that does not include `site:acme.com` and any count above 10.

Tool constraints support the same comparison, set, and logical operators as datasource filters, plus additional string operators (`$contains`, `$starts_with`, `$ends_with`, `$matches_regex`) and length operators (`$max_length`, `$min_length`).

## How enforcement works

Execution policies are hardrails, enforced at three points in a defense-in-depth model that operates around the LLM rather than relying on it.

**Before the LLM call.** The platform builds the agent's tool schemas and datasource schemas according to the policy. Disabled tools and inaccessible tables are removed from the schemas the agent sees. Constraint descriptions are annotated into parameter descriptions so the agent understands the boundaries it must operate within.

**During data access.** When the agent queries a datasource, the platform applies the policy's filters to the query itself. For table queries, filter conditions are enforced so only matching rows are returned. For document retrieval, filter conditions are added to the vector search query. The agent receives only data that passes the policy's filters.

**At tool execution.** When the agent invokes a tool, the platform validates every argument against the policy's constraints before dispatching the call. If any argument violates a constraint, the call is rejected and the agent receives an error.

This model means policies cannot be circumvented through prompt injection or creative instructions. The LLM never sees the authorization data that drives datasource scoping. Tool constraints are validated outside the LLM's execution path.

<Note>
  Execution policies default to denying access and narrowing scope rather than expanding it. If a datasource referenced in a policy does not exist, the platform rejects the policy. If a table referenced in a filter is not in the datasource, initialization fails. If a document does not match a filter, it is invisible.
</Note>

## Composing policies

Multiple execution policies can be composed together, and the platform merges them structurally rather than choosing one over another. This is useful when different concerns are managed by different policies: one policy might handle data region scoping, another might handle tool restrictions, and a third might handle column redaction.

When policies are composed:

* **Overlapping entries** for the same datasource or tool have their constraints merged with `$and`, meaning the data or parameter must satisfy all policies to be accessible.
* **Disabled is sticky.** If any policy disables a datasource or tool, it stays disabled in the composed result regardless of other policies.

Policies can be set at multiple levels that compose together in order:

1. **Agent definition**: default policies baked into the agent, applied to every session.
2. **Session creation**: policies passed when creating a session, layered on top of the agent defaults.

Because composition only narrows access (filters intersect, disabled is sticky), a session-level policy cannot grant access beyond what the agent definition allows. Each layer can only further restrict the previous one.

## Related concepts

Execution policies interact with other parts of the platform:

<CardGroup cols={2}>
  <Card title="Agents" icon="robot" href="/concepts/agents">
    The agents that execution policies constrain, including their datasource bindings and tool configurations.
  </Card>

  <Card title="Context Engineering" icon="brain" href="/concepts/context-engineering">
    How datasources are ingested into the data elements that execution policies scope.
  </Card>

  <Card title="Batch Jobs" icon="layer-group" href="/concepts/batch-jobs">
    Running agents at scale with execution policies applied to each batch execution.
  </Card>
</CardGroup>
