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
pip install kitelogik semantic-kernelsemantic-kernel is not a hard dependency — only imported when you call kernel_plugin().
Setup
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.
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
from semantic_kernel import Kernel
kernel = Kernel()
adapter.add_to_kernel(kernel, plugin_name="kitelogik")2. Pull the plugin yourself
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:
SemanticKernelAdapter(
gate: PolicyGate,
context: SessionContext,
sanitize: bool = True,
deny_message: str | None = None,
)| Param | Default | Purpose |
|---|---|---|
sanitize | True | Run 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.