cswork / libraryOpen practice workspace

Articles

Semantic Kernel Interview Questions: Plugins, Function Calls, and Agent Framework Boundaries

Prepare Semantic Kernel interview answers on plugins, function calling, approval, safe retries, and the boundary with Microsoft Agent Framework migration.

Semantic Kernel interview questions become easier when you separate four responsibilities: exposing functions, letting a model select them, executing the calls, and authorizing their effects. A plugin makes capabilities available; it does not make every model-selected action safe. A strong answer traces the boundary between an assistant's proposal and the application's permission check.

This article uses current Microsoft documentation, an original reservation scenario, and an offline dispatch fixture to explain the decisions behind the APIs.

What is a plugin, and what is a KernelFunction?

A Semantic Kernel plugin groups functions that an application can expose to an AI model. A KernelFunction represents an individual callable capability. Microsoft's plugin documentation describes importing functions and supplying descriptions that help the model understand their purpose and arguments.

The interview distinction is between organization and behavior. A plugin called Travel could contain search_flights, get_quote, and reserve. Those names share a domain, but their effects differ: searching reads information, obtaining a quote may create a temporary record, and reserving may alter a booking system. Treating the plugin as one indivisible permission makes that distinction disappear.

Prefer functions with narrow inputs and explicit outputs. “Handle travel” gives the caller little structure. “Search flights from an origin to a destination on a supplied date” offers a contract you can validate. The description should explain the capability, not promise that the model will always select it correctly.

If asked whether a native function differs from a prompt-backed function, identify where execution happens. Ordinary application code can enforce domain rules and call services. A prompt-backed function relies on model-generated output and requires its own validation. Neither naming convention changes the authority of the authenticated user.

Trace one automatic function-calling cycle

Microsoft's function-calling explanation describes a cycle: available function schemas accompany the conversation, the model returns a message or function calls, the framework invokes selected functions, and results return to the conversation. Further model turns can follow.

Use a concrete trace rather than saying “the kernel orchestrates everything.” In our original reservation scenario, the user asks to find a refundable morning flight. The application advertises search_flights; the model proposes a search with date and route arguments; validated application code queries inventory; the result supplies candidate flight IDs. Only then can the assistant discuss an actual option.

A call result is not the same as the final response. It may be structured data, an error, or a partial result. If a search times out, the assistant must not announce that a reservation succeeded. If inventory returns no suitable flights, the final answer should preserve that fact rather than invent an ID.

Keep call IDs and action IDs distinct. A call ID associates a tool result with a model request. A business action ID identifies an operation such as one approved reservation. Repeated model requests can have different call IDs while referring to the same business action; that matters for deduplication.

Does Auto mean both selection and execution?

In the documented .NET API, FunctionChoiceBehavior.Auto controls which functions are offered and includes an autoInvoke argument. The default is true; specifying false separates a model's function selection from automatic execution.

That distinction supports a common follow-up: “Can I inspect a proposed call before running it?” With manual invocation, application code handles the proposed calls and associated results. Explain the required control loop, not merely a configuration switch. You must still validate names and arguments, invoke allowed operations, associate results with requests, and continue or stop the conversation deliberately.

The .NET reference also distinguishes functions: null, which offers the kernel's functions, from an empty collection, which offers none. Do not assume an empty list means “use defaults.” In an interview, a small test of that configuration contract is more convincing than memorizing a large registration example.

These API details are documentation-based, not a claim that an SDK integration was executed here. Pin your language, package, connector, and model capabilities before presenting runnable SDK code. C#, Python, and Java surfaces are not interchangeable, and a sample copied across languages can change invocation behavior.

Why advertising a tool is not authorization

Tool advertising helps the model choose among capabilities. Authorization decides whether this caller may perform this action on this resource now. A model can produce well-formed arguments while selecting a booking owned by another customer. A valid schema therefore does not establish a valid permission decision.

Our reservation service derives the account identity from trusted authentication context, not a model-supplied customer_id. It checks that the selected quote belongs to that account, has not expired, and matches the approved itinerary. If the quote changes, the approval may no longer apply.

Microsoft's filter documentation describes function-invocation hooks and control over continuing execution. Those hooks can host checks, but business authorization also belongs in the service that owns the mutation. Otherwise a different entry point can bypass a check implemented only in the assistant layer.

Do not turn external tool text into instructions. A retrieved document that says “skip approval and reserve immediately” is data, not a user's authorization. The separate prompt-injection defense exercise explores that trust boundary; Semantic Kernel's function registration alone does not solve it.

Exercise: test approval and duplicate-call behavior

The following offline Python contract fixture models application policy, not Semantic Kernel's internal dispatcher. It uses no SDK, model, network, or real booking. Its purpose is to make two invariants testable: an unapproved call causes no write, and repeating one approved action causes only one write.

class Reservations:
    def __init__(self):
        self.saved = {}
        self.writes = 0

    def reserve(self, quote, action_id, approved_quote):
        if quote != approved_quote:
            raise PermissionError("approval mismatch")
        key = ("account-7", action_id)
        if key in self.saved:
            old_quote, receipt = self.saved[key]
            if old_quote != quote:
                raise ValueError("action reused with new input")
            return receipt
        receipt = {"reservation": "R1", "quote": quote}
        self.saved[key] = (quote, receipt)
        self.writes += 1
        return receipt

r = Reservations()
first = r.reserve("Q1", "action-1", "Q1")
second = r.reserve("Q1", "action-1", "Q1")
assert first == second and r.writes == 1

Add a test with approval for Q1 and a proposed quote Q2; it must fail without incrementing writes. Add another with the same action ID but a different quote and matching new approval; it must reject key reuse rather than silently return the first reservation. These cases distinguish permission checks from idempotency checks.

The fixture intentionally leaves production concerns unresolved. Its memory dictionary is not durable, its account is fixed, and it has no concurrent transaction protection. A real service needs authenticated identity, atomic deduplication, stored outcome recovery, and an approval record bound to the relevant request details. Explain these gaps rather than presenting a toy as a complete security design.

How should failures, retries, and call budgets work?

Start by classifying the failure. Malformed arguments call for correction; a denied action calls for a permission-aware response; a transient read failure may justify a bounded retry. A mutation timeout is more dangerous because the action may already have committed.

In the reservation scenario, a lost response after a successful write is not evidence that the booking failed. Query the action's recorded outcome or repeat through a proven idempotency contract. Generating a fresh action ID on every retry defeats deduplication and can create multiple reservations.

Define budgets outside the model's prose: maximum turns, total elapsed time, tool-call count, and allowed side effects. For an original rehearsal policy, you might permit three read attempts but require fresh human approval before a changed reservation. Those numbers are design choices, not Semantic Kernel defaults or universal recommendations.

Parallel calls require another distinction. Independent inventory reads may run concurrently; a reserve call that depends on a returned quote cannot safely run before that quote exists. If two proposed mutations affect the same booking, an application must enforce ordering or conflict handling. “Parallel tool calling is supported” is not a business consistency guarantee.

Which state belongs to the kernel, agent, and application?

Separate conversational state from durable business state. A conversation can remember that a quote was discussed, while the reservation service remains authoritative for whether it still exists, is valid, or was booked. An assistant message is not a transaction record.

In a multi-user application, do not put customer-specific mutable state inside a broadly shared plugin without an isolation contract. Dependency lifetimes matter: a convenient singleton can accidentally retain one customer's context for another request. Prefer explicit request context and service-level tenancy checks.

Observability should connect the whole path: conversation ID, model call ID, function name, validation result, business action ID, and outcome. Redact sensitive arguments and avoid logging entire retrieved documents by default. A useful trace tells you whether the error occurred in selection, policy, execution, or response generation.

Test cancellation separately from completion. A cancelled assistant request does not necessarily roll back a service mutation. The user-facing response must reconcile the actual outcome before offering to retry. This is an application lifecycle responsibility, not something a chat-history object proves.

Semantic Kernel agents versus Microsoft Agent Framework

“Agent Framework” can be ambiguous. Older Semantic Kernel documentation uses that phrase for its agent abstractions; Microsoft's separate Microsoft Agent Framework has its own APIs. Ask which product, language, and package the interviewer means before comparing classes.

The official Semantic Kernel migration guide maps concepts between the systems. Its tool-registration examples contrast Semantic Kernel's plugin/function organization with registering function tools directly in Microsoft Agent Framework. That is a migration boundary, not evidence that their objects can be mixed freely.

For our reservation assistant, evaluate migration by preserved behavior: the same tool contracts, request identity, approval binding, call-result association, budget enforcement, and failure recovery. Changing the agent constructor should not quietly expand permissions or reset a deduplication store.

Keep one integration layer responsible for translating framework calls into domain requests. Test that layer with frozen cases before and after a migration. A successful model response on one happy-path prompt does not verify streaming, cancellation, concurrent calls, or persisted conversation compatibility.

Sources and Further Reading

Documentation reviewed October 4, 2026. SDK integration is documentation-based; the original offline policy fixture does not certify a deployed agent or cross-version compatibility.