# How the Kimi CLI Approval System Controls Tool Execution Authorization

> Discover how the Kimi CLI approval system controls tool execution authorization. Learn about its validation, auto-approval, and user consent mechanisms for safe operations.

- Repository: [Moonshot AI/kimi-cli](https://github.com/MoonshotAI/kimi-cli)
- Tags: internals
- Published: 2026-07-20

---

**The Kimi CLI approval system intercepts every tool call through the `Approval` class in [`src/kimi_cli/soul/approval.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py), validating execution context and routing requests through auto-approval logic or interactive user consent before allowing potentially destructive operations to proceed.**

Kimi CLI implements a robust permission gate to prevent unauthorized tool execution. According to the [MoonshotAI/kimi-cli](https://github.com/MoonshotAI/kimi-cli) source code, the approval system centered in [`src/kimi_cli/soul/approval.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py) provides both automatic and manual authorization paths while maintaining comprehensive audit trails for every decision.

## Architecture of the Approval System

The approval workflow is orchestrated by the `Approval` class, which acts as a mandatory checkpoint between the AI agent and tool execution.

### Core Entry Point and Context Validation

Tool implementations initiate authorization by invoking [`await approval.request(...)`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L200-L210). This method accepts four critical parameters:

- **sender**: The tool name (e.g., `"shell"`, `"file_editor"`)
- **action**: A machine-readable identifier for the operation
- **description**: Human-readable context for the UI
- **display**: Optional UI blocks (diffs, shell commands, etc.)

Before processing, the system validates that the call originates from an active tool execution context using `get_current_tool_call_or_none`. If validation fails, the method aborts immediately with a `RuntimeError` ([lines 223-226](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L223-L226)).

## Auto-Approval Modes for Unattended Operation

The approval system supports bypass mechanisms for automated workflows while preserving telemetry records.

### Yolo and AFK Flags

When `self.is_auto_approve()` returns `True` (indicating Yolo or AFK mode), the system bypasses user interaction entirely. It emits a `tool_approved` telemetry event ([lines 42-50](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L42-L50)) and returns `ApprovalResult(approved=True)` immediately.

### Session-Wide Auto-Approval

Users can opt to approve specific actions for the entire session. The system maintains `_state.auto_approve_actions` as a registry of pre-authorized operations. When a request matches an entry in this cache, it receives automatic approval without UI interruption ([lines 62-70](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L62-L70)).

## Manual Authorization Flow

When no auto-approval rule applies, the system enters an interactive blocking flow:

1. **Request Registration**: Creates a unique request ID and registers it with `ApprovalRuntime`
2. **UI Blocking**: Suspends tool execution via `await self._runtime.wait_for_response(request_id)`
3. **User Response Processing**: Handles three possible responses from the UI layer:
   - **`"approve"`**: Executes the tool immediately
   - **`"approve_for_session"`**: Executes the tool **and** adds the action to `auto_approve_actions` ([lines 70-78](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L70-L78))
   - **`"reject"`**: Aborts execution and optionally raises `ToolRejectedError`

## Session Cache Persistence

When a user selects *"approve for session"*, the system resolves pending requests automatically. The `resolve` method updates all queued instances of the same action with `approved_via_session_cache=True` ([lines 72-79](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L72-L79)), ensuring the UI reflects the updated authorization state without requiring individual confirmations.

## Telemetry and Audit Trails

Every authorization decision records detailed metrics through `_track_permission_result` ([lines 36-48](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L36-L48)). The telemetry captures:

- **Step number** and **tool name**
- **Permission mode**: `auto`, `yolo`, or `manual`
- **Result status**: `approved`, `rejected`, `cancelled`, or `error`
- **Approval surface**: Derived from the first `DisplayBlock` type
- **Duration** and **session cache writes**
- **User feedback** content

This implementation mirrors the TypeScript `permissionGateService` contract (as noted in comments at [line 47](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L47)), ensuring compatibility with existing observability infrastructure.

## Implementation Example

Tool developers integrate approval checks using the `Approval` class:

```python
from kimi_cli.soul.approval import Approval

async def run_command(tool_input: str) -> str:
    approval = Approval()
    result = await approval.request(
        sender="shell",
        action="run_shell_command",
        description=f"Execute: {tool_input}",
        display=[DisplayBlock(type="shell", content=tool_input)],
    )
    if not result:
        raise result.rejection_error()
    return await execute_shell(tool_input)

```

The manual approval flow triggers automatically when the UI presents the request:

```python

# When user selects "Approve for this session":

# 1. Action added to auto_approve_actions

# 2. Pending identical requests resolved via runtime.resolve()

# 3. Tool receives ApprovalResult(approved=True)

# 4. Telemetry logs tool_approved with session_cache_write=True

```

## Summary

- **Entry Point**: The [`Approval.request`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L200-L210) method validates context and initiates authorization checks
- **Auto-Approval**: Yolo/AFK flags and session caches bypass UI for trusted workflows
- **Manual Flow**: Blocking wait for user input with support for one-time or session-wide approval
- **Persistence**: Session caches automatically resolve pending identical requests
- **Observability**: Comprehensive telemetry tracks permission modes, results, and user feedback

## Frequently Asked Questions

### How does Kimi CLI prevent unauthorized tool execution?

The system validates every tool call originates from an active execution context using `get_current_tool_call_or_none` ([lines 223-226](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L223-L226)). Without this validation, the request aborts immediately. Valid requests then route through the approval decision tree requiring explicit authorization unless auto-approved.

### What is the difference between Yolo mode and session-wide approval?

**Yolo mode** (and AFK flags) bypasses all authorization checks immediately, automatically approving every request without UI interaction or persistence. **Session-wide approval** requires an initial manual approval with the *"approve for session"* option, which then persists that specific action to `auto_approve_actions` for the duration of the session while still logging telemetry for each execution.

### How does the approval system track user decisions?

The `_track_permission_result` method ([lines 36-48](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/approval.py#L36-L48)) records step numbers, tool identifiers, permission modes (auto/yolo/manual), results (approved/rejected/cancelled/error), approval surfaces, durations, and session cache writes. This data emits as `tool_approved` or `tool_rejected` events for audit trails.

### Can tool executions be approved automatically without user interaction?

Yes. Two mechanisms enable automatic approval: global flags like Yolo/AFK mode that bypass all checks, or session-wide auto-approval where specific actions are pre-authorized after initial user consent. Both paths emit telemetry events and return `ApprovalResult(approved=True)` without blocking for UI input.