Skip to content

LlamaIndex adapter

For LlamaIndex agents — ReActAgent, OpenAIAgent, FunctionAgent, etc. Returns llama_index.core.tools.FunctionTool instances whose sync and async paths both run through the governance pipeline, so it doesn't matter which agent flavour or worker you're using.

Module name

The Python package is llama_index (with underscore), but Kite Logik's adapter import is kitelogik.adapters.llamaindex (no underscore) — matching the module file llamaindex.py.

Install

bash
pip install kitelogik llama-index

llama-index is not a hard dependency — only imported when you call llamaindex_tools().

Setup

python
from kitelogik import OPAClient, PolicyGate, SessionContext
from kitelogik.adapters.llamaindex import LlamaIndexAdapter

gate = PolicyGate(opa_client=OPAClient())
context = SessionContext(
    session_id="sess_001",
    user_role="analyst",
    session_scopes=["read_customer", "search_docs"],
)

adapter = LlamaIndexAdapter(gate=gate, context=context)

Register tools

register(name, fn, description="", action=None) — chainable.

python
def get_customer(customer_id: str) -> str:
    """Look up a customer record by ID."""
    return f"Customer {customer_id}: Acme Corp"

async def search_docs(query: str) -> str:
    return f"Top results for: {query}"

adapter.register("get_customer", get_customer, description="Look up a customer")
adapter.register("search_docs",  search_docs,  description="Search internal docs")

Both sync and async functions work. The adapter builds a single governed async wrapper per tool and exposes it through both the sync (fn=) and async (async_fn=) parameters of FunctionTool.from_defaults — so an agent that calls tool.call(...) and one that calls await tool.acall(...) both flow through the same policy gate.

Pass governed tools to a LlamaIndex agent

python
from llama_index.core.agent import ReActAgent
from llama_index.llms.openai import OpenAI

agent = ReActAgent.from_tools(
    adapter.llamaindex_tools(),    # ← governed FunctionTool list
    llm=OpenAI(model="gpt-4o"),
)

response = agent.chat("Look up customer cust_001 and summarise.")

Or the newer FunctionAgent flow — same tools= argument shape.

What happens on a deny

Denied calls return a JSON string {"blocked": true, "reason": "..."} from the tool — the agent loop continues; the model sees the structured denial.

To customise, pass deny_message= to the adapter constructor.

Constructor parameters

LlamaIndexAdapter extends BaseGovernedAdapter:

python
LlamaIndexAdapter(
    gate: PolicyGate,
    context: SessionContext,
    sanitize: bool = True,
    deny_message: str | None = None,
)
ParamDefaultPurpose
sanitizeTrueRun prompt-injection sanitiser on string return values
deny_message"Action blocked by governance policy."Surfaced to the model on deny

Source

kitelogik/adapters/llamaindex.py on GitHub.

Released under the Apache 2.0 License.