Skip to content

Semantic Kernel adapter

For Microsoft Semantic Kernel. Semantic Kernel registers tools as plugins — Python objects whose methods are decorated with @kernel_function. The adapter builds that plugin object dynamically: each registered function becomes a governed @kernel_function method on a single plugin class.

Install

bash
pip install kitelogik semantic-kernel

semantic-kernel is not a hard dependency — only imported when you call kernel_plugin().

Setup

python
from kitelogik import OPAClient, PolicyGate, SessionContext
from kitelogik.adapters.semantic_kernel import SemanticKernelAdapter

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

adapter = SemanticKernelAdapter(gate=gate, context=context)

Register tools

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

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

adapter.register("get_customer", get_customer, description="Look up a customer")

Add to a Kernel

Two equivalent ways — both produce the same registered plugin:

1. Convenience helper

python
from semantic_kernel import Kernel

kernel = Kernel()
adapter.add_to_kernel(kernel, plugin_name="kitelogik")

2. Pull the plugin yourself

python
kernel = Kernel()
kernel.add_plugin(adapter.kernel_plugin(), plugin_name="kitelogik")

Both register a single plugin called kitelogik (override via plugin_name=) whose methods are your governed tools.

What happens on a deny

Denied calls return a JSON string {"blocked": true, "reason": "..."} from the kernel function — the agent / planner sees the structured denial in its next turn.

To customise the message, pass deny_message= to the adapter constructor.

Constructor parameters

SemanticKernelAdapter extends BaseGovernedAdapter:

python
SemanticKernelAdapter(
    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

Backwards-compatible alias

adapter.kernel_functions() returns the same plugin instance that kernel_plugin() does. Older code that called kernel_functions() expecting a list is incorrect — Semantic Kernel's API is plugin-shaped, not list-shaped, and both names return the plugin.

Source

kitelogik/adapters/semantic_kernel.py on GitHub.

Released under the Apache 2.0 License.