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

# LlamaIndex

> Tool wrappers that inject AtlaSent authorization into LlamaIndex agents, in Python and TypeScript.

The AtlaSent LlamaIndex integration wraps the functions behind your LlamaIndex tools with authorize-before-execute semantics: every call is evaluated against `/v1/evaluate`, its Permit is verified, and only then does the original function run. The wrappers have no dependency on LlamaIndex itself, so they work with any LlamaIndex version.

## Install

<Warning>
  **Not yet published.** `atlasent-llamaindex` is not yet on PyPI and `@atlasent/llamaindex` is not yet on
  npm, so the install commands below do not work yet. Until a release is
  published, install from source: [`python/atlasent_llamaindex`](https://github.com/Atlasent/atlasent-sdk/tree/main/python/atlasent_llamaindex)
  and [`typescript/packages/llamaindex`](https://github.com/Atlasent/atlasent-sdk/tree/main/typescript/packages/llamaindex)
  in the `atlasent-sdk` repository.
</Warning>

<CodeGroup>
  ```bash Python theme={null}
  pip install atlasent-llamaindex atlasent
  ```

  ```bash TypeScript theme={null}
  npm install @atlasent/llamaindex @atlasent/sdk
  ```
</CodeGroup>

## Python

`with_llamaindex_guard` wraps a callable before you hand it to `FunctionTool.from_defaults`, `QueryEngineTool`, or any other LlamaIndex tool factory. The wrapped function keeps the original name, docstring, and signature.

```python theme={null}
import os

from atlasent import AtlaSentClient
from atlasent_llamaindex import with_llamaindex_guard
from llama_index.core.tools import FunctionTool

client = AtlaSentClient(api_key=os.environ["ATLASENT_API_KEY"])

def search(query: str) -> str:
    """Search the knowledge base."""
    return f"Results for: {query}"

guarded_search = with_llamaindex_guard(
    search,
    client,
    agent="service:knowledge-bot",
    # agent.tool.invoke (the default action) requires `environment`
    extra_context={"environment": "production"},
    # Action classes require a state snapshot by default (SNAPSHOT_REQUIRED otherwise)
    state_snapshot={"source": "knowledge-bot", "complete": True},
)

tool = FunctionTool.from_defaults(fn=guarded_search)
```

If the policy denies the call, `AtlaSentDeniedError` is raised before `search()` runs. For async tools, use `async_with_llamaindex_guard` with an `AsyncAtlaSentClient`.

## TypeScript

`withLlamaIndexGuard` takes an array of tool definitions (LlamaIndex-style `metadata` plus an `execute` callback) and returns the same tools with `execute` replaced by an authorize-first version: evaluate, then verify the Permit, then execute.

```typescript theme={null}
import { AtlaSentClient } from "@atlasent/sdk";
import { FunctionTool } from "llamaindex";
import { withLlamaIndexGuard } from "@atlasent/llamaindex";

const client = new AtlaSentClient({ apiKey: process.env.ATLASENT_API_KEY! });

const guarded = withLlamaIndexGuard(
  [
    {
      metadata: {
        name: "vector_search",
        description: "Semantic search over the knowledge base",
        parameters: {
          type: "object",
          properties: { query: { type: "string" } },
          required: ["query"],
        },
      },
      execute: async ({ query }) => vectorStore.search(query),
    },
  ],
  client,
  {
    agent: "service:knowledge-bot",
    extraContext: { environment: "production" },
    // Action classes require a state snapshot by default (SNAPSHOT_REQUIRED otherwise)
    stateSnapshot: { source: "knowledge-bot", complete: true },
  },
);

const tools = guarded.map((t) => FunctionTool.from(t.execute, t.metadata));
```

`agent`, `action`, `extraContext`, and `stateSnapshot` also accept a resolver function `(toolName, input) => value`, so you can set them per call.

## Denials

By default a denial throws (`AtlaSentDeniedError`). Set `on_deny="tool-result"` in Python, or `onDeny: "tool-result"` in TypeScript, to return a structured denial instead, so the LLM sees the reason and can adjust. In Python that's a `DenialResult` object; in TypeScript it looks like:

```json theme={null}
{ "denied": true, "decision": "deny", "evaluationId": "...", "reason": "..." }
```

A failed Permit verification is treated as a denial. Object results from an authorized call are annotated with `_atlasent_permit_id` and `_atlasent_audit_hash`; other results pass through unchanged.

## Action class mapping

When you don't pass an action, the wrappers evaluate the canonical `agent.tool.invoke` action and always send the tool's own name as `context.tool`, so policy can tell tools apart. That action class requires `environment` in context; the wrapper never invents one, so supply it through `extra_context` / `extraContext`. If you map tools to your own action classes instead, key them on stable action types rather than Python or TypeScript function names.

## Related

* [LangChain integration](/integrations/langchain)
* [MCP server](/integrations/mcp-server) for host-side gating


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.