# How to Implement Tool Approval and Permission Gating Mechanisms in Kimi-Code

> Implement tool approval and permission gating in Kimi-Code with a dual-layer architecture. Learn how to separate human approval flows from automated policy enforcement for robust control.

- Repository: [Moonshot AI/kimi-code](https://github.com/MoonshotAI/kimi-code)
- Tags: how-to-guide
- Published: 2026-07-27

---

**Kimi-Code implements tool approval and permission gating through a dual-layer architecture that separates human-in-the-loop approval flows from automated policy enforcement using permission modes and rules.**

MoonshotAI/kimi-code is an open-source AI coding agent framework that isolates tool execution behind two complementary mechanisms. Understanding how to implement tool approval and permission gating mechanisms allows you to build secure, policy-compliant agent workflows that require explicit human authorization for sensitive operations while automatically approving safe, repetitive tasks.

## The Approval Flow: From Emission to Resolution

When an agent issues a tool call, Kimi-Code creates a structured approval workflow that persists in the session transcript and exposes REST endpoints for client interaction.

### Creating ToolCallFrame and Pending Interactions

The framework instantiates a `ToolCallFrame` that may contain an `approvalId` when a tool call requires supervision. According to the source code in [`packages/transcript/src/model/interaction.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/transcript/src/model/interaction.ts), this links to an `Interaction` object with `kind: 'approval'` stored in the transcript. The session's `pending_interaction` field transitions to `'awaiting_approval'`, as defined in [`packages/klient/src/core/facade/session.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/klient/src/core/facade/session.ts).

The pending state remains until resolved via the REST API or automated rules. All approval state schemas are strictly validated using Zod in [`packages/protocol/src/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/approval.ts).

### Fetching Pending Approvals via REST

Clients poll for pending approvals using the endpoint defined in [`packages/protocol/src/rest/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/rest/approval.ts):

```typescript
GET /v1/sessions/{session_id}/approvals?status=pending

```

This returns the `approval_id`, tool name, input preview, and expiration. The response structure follows `approvalResponseSchema`, ensuring type safety between server and client implementations.

### Resolving Approval States

To resolve a pending approval, the client submits a POST request to the same endpoint with an `ApprovalResponse` payload:

```typescript
POST /v1/sessions/{session_id}/approvals/{approval_id}

```

Valid decisions include `approved`, `rejected`, or `cancelled`. The server validates against `approvalResponseSchema` before updating the transcript entry and transitioning the session status from `awaiting_approval` back to `running`. This logic is implemented in [`packages/agent-core/src/services/approval/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/services/approval/approval.ts).

## Configuring Permission Gating with Rules

Permission gating determines the default policy for whether tool calls require explicit approval, controlled through `Session.agent_config.permission_mode` and `PermissionRule` objects defined in [`packages/protocol/src/session.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/session.ts).

### Understanding Permission Modes

The `permission_mode` field accepts three string values that dictate engine behavior:

- **`manual`** – Every tool call generates a pending approval, ensuring maximum human oversight.
- **`auto`** – Calls proceed automatically only if a matching `PermissionRule` exists; otherwise falls back to manual review.
- **`yolo`** – All calls auto-approve immediately, bypassing the entire approval pipeline (use with caution).

The default mode is configurable at the server level via `default_permission_mode`, as demonstrated in [`packages/node-sdk/test/create-session-transport.test.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/node-sdk/test/create-session-transport.test.ts).

### Defining PermissionRule Objects

Permission rules follow the `permissionRuleSchema` structure stored in `session.permission_rules`. Each rule contains:

- **`tool_name`** – The target tool identifier (e.g., `"Bash"`, `"FileWrite"`).
- **`matcher`** – Optional conditional filter supporting `command_prefix`, `path_glob`, `exact_input`, or `always`.
- **`decision`** – Currently supports only `'approved'`, with planned extensibility for rejection rules.

When the engine evaluates a tool call, it executes the `shouldAwaitApproval(toolName, input)` function in [`packages/agent-core/src/services/approval/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/services/approval/approval.ts). This function checks the current mode and rule set, returning `true` only when a manual approval is required.

## Runtime Engine Integration

The approval pipeline integrates deeply with session lifecycle management and transcript publishing.

### Session Creation and Dynamic Updates

When initializing a session, clients specify the initial `permission_mode` and rule set through `sessionCreateSchema` in [`packages/protocol/src/session.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/session.ts). The specification allows pre-configuring safe tools for automatic approval while flagging sensitive operations for manual review.

Clients may update permissions at runtime using `sessionUpdateSchema`. This patches `session.permission_rules` and immediately affects subsequent tool call evaluations without requiring session restart.

### Transcript Publishing and UI Synchronization

The transcript service publishes `awaiting_approval` status changes, enabling UI clients like `kimi-web` and `kimi-code` to surface notification badges and approval queues. Each `Interaction` object maintains a link to its corresponding `ToolCallFrame` via `approvalId`, creating a complete audit trail of human decisions within the session transcript.

## Implementation Examples

### Define a Session with Auto-Approval for Specific Tools

Create a session that automatically approves Bash tool calls while requiring manual review for others:

```typescript
import { SessionCreate } from '@moonshot-ai/protocol';
import { SessionClient } from '@moonshot-ai/klient';

const sessionSpec: SessionCreate = {
  title: 'Demo session',
  agent_config: {
    permission_mode: 'auto',
  },
  permission_rules: [
    {
      id: 'rule-1',
      tool_name: 'Bash',
      matcher: { kind: 'always' },
      decision: 'approved',
      created_at: new Date().toISOString(),
      created_by: 'user',
    },
  ],
};

await SessionClient.create(sessionSpec);

```

This configuration references the `sessionCreateSchema` available in [`packages/protocol/src/session.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/session.ts).

### Fetch Pending Approvals

Monitor active sessions for tool calls awaiting human review:

```typescript
import { SessionClient } from '@moonshot-ai/klient';

const pending = await SessionClient.getPendingApprovals(sessionId);
for (const appr of pending) {
  console.log(`Approve ${appr.tool_name} call ${appr.tool_call_id}?`);
}

```

The underlying endpoint is defined in [`packages/protocol/src/rest/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/rest/approval.ts).

### Resolve an Approval Decision

Programmatically approve or reject pending tool calls:

```typescript
import { SessionClient } from '@moonshot-ai/klient';

await SessionClient.resolveApproval(sessionId, approvalId, {
  decision: 'approved',
  // optional: scope: 'session', feedback: 'looks good'
});

```

This implements the `approvalResolveRequestSchema` from the protocol definitions.

### Change Permission Mode at Runtime

Switch from auto-approval to manual oversight mid-session:

```typescript
await SessionClient.update(sessionId, {
  permission_mode: 'manual',
});

```

This utilizes the `sessionUpdateSchema` validation in [`packages/protocol/src/session.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/session.ts).

## Summary

- **Dual-layer security**: Kimi-Code separates human approval workflows (`Interaction` objects) from automated policy enforcement (`permission_mode` and `PermissionRule`).
- **Three permission modes**: Configure sessions using `manual` (always approve), `auto` (rule-based), or `yolo` (always auto-approve) via [`packages/protocol/src/session.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/session.ts).
- **RESTful approval API**: Manage pending approvals through `GET` and `POST` endpoints defined in [`packages/protocol/src/rest/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/rest/approval.ts), with strict Zod schema validation.
- **Engine decision logic**: The `shouldAwaitApproval()` function in [`packages/agent-core/src/services/approval/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/services/approval/approval.ts) evaluates rules and modes to determine if a tool call requires human intervention.
- **Transcript integration**: All approval states persist as `Interaction` objects linked to `ToolCallFrame` instances, creating complete audit trails within session transcripts.

## Frequently Asked Questions

### What is the difference between permission_mode 'auto' and 'yolo'?

**`auto`** mode requires explicit `PermissionRule` definitions to auto-approve specific tools; any unmatched tool call falls back to manual approval. **`yolo`** mode bypasses all rule checking and immediately approves every tool call without creating pending `Interaction` objects or transcript entries, suitable only for trusted, isolated environments.

### How do I create permission rules that match specific command patterns?

Use the `matcher` field within your `PermissionRule` object to specify conditional logic. The matcher supports `command_prefix` (approves commands starting with specific strings), `path_glob` (file path patterns), `exact_input` (string matching), or `always` (unconditional approval for the tool). Define these in `sessionCreateSchema` or update them dynamically via `sessionUpdateSchema`.

### Where does the approval decision logic execute in the codebase?

The core evaluation occurs in the `shouldAwaitApproval(toolName, input)` function within [`packages/agent-core/src/services/approval/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/services/approval/approval.ts). This service checks the current session's `permission_mode` and iterates through `permission_rules` to determine whether to create a pending `Interaction` or allow immediate execution.

### Can I implement custom approval UIs using the protocol definitions?

Yes. The protocol package exposes all necessary schemas and REST endpoint types in [`packages/protocol/src/rest/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/rest/approval.ts) and [`packages/protocol/src/approval.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/approval.ts). You can build custom clients that poll `GET /v1/sessions/{session_id}/approvals` and submit resolutions via `POST /v1/sessions/{session_id}/approvals/{approval_id}`, following the `approvalResponseSchema` for payload validation.