
从零实现自定义 Soul用 Kimi Code CLI 的 Shell UI 运行你自己的 Agent 循环【免费下载链接】kimi-cliKimi Code CLI is your next CLI agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kimi-cli导读examples/custom-echo-soul是 Kimi Code CLI 仓库中一个极简但完整的示例演示了如何不依赖内置 LLM 与工具链仅凭一个自定义SoulAgent 循环实现接入 Kimi Code CLI 的交互式ShellUI。读完本文你将掌握 Soul 协议的全部接口约定、Wire 消息的发送方式以及如何把任意自定义 Agent 循环嵌入 Kimi CLI 的终端界面中运行为构建自己的 Agent 打下基础。示例定位Soul 是 Agent 循环的最小契约在 Kimi Code CLI 的架构中Soul是驱动整个交互的核心抽象它定义了一次用户输入进来之后Agent 如何运行的契约。Kimi CLI 的ShellUI 并不关心你的 Soul 背后是真实的大模型、脚本模拟器还是简单的回显逻辑它只依赖Soul协议约定的一组属性与方法。examples/custom-echo-soul/目录结构如下examples/custom-echo-soul/ ├── README.md # 运行说明 ├── main.py # EchoSoul 实现与入口 └── pyproject.toml # 依赖声明README.md给出的运行方式只有三条命令cd examples/custom-echo-soul uv sync --reinstall uv run main.py但这三条命令背后是一个完整的自定义 Agent 接入 Kimi CLI Shell UI的工程范式用uv管理依赖、通过本地路径引用仓库根目录下的kimi-cli包、以几十行代码实现一个可交互的 Agent。运行环境与依赖声明示例的 pyproject.toml 揭示了接入 Kimi CLI 的最低依赖要求[project] name custom-echo-soul version 0.1.0 description Add your description here readme README.md requires-python 3.13 dependencies [kimi-cli, kosong] [tool.uv.sources] kimi-cli { path ../../ }几个关键点requires-python 3.13项目要求 Python 3.13 及以上这与仓库主体src/kimi_cli的语言版本要求一致dependencies [kimi-cli, kosong]kimi-cli提供Soul协议、ShellUI 与 Wire 消息类型kosong是底层消息/Provider 模型库示例中ContentPart、TextPart等类型最终都来自kosong.message见 src/kimi_cli/wire/types.py 的 re-export[tool.uv.sources]中的path ../../由于示例位于examples/custom-echo-soul/../../指向仓库根目录即让uv直接使用本地源码而非 PyPI 发布版保证示例与当前仓库代码完全同步。执行uv sync --reinstall会按上述声明构建隔离环境--reinstall强制重新安装依赖避免缓存干扰随后uv run main.py即可在虚拟环境中启动程序。Soul 协议你需要实现的全部接口要让ShellUI 接受你的自定义 Agent对象必须满足Soul协议。该协议定义在 src/kimi_cli/soul/init.py是一个runtime_checkable的Protocol包含以下成员成员类型说明namestrpropertySoul 的名称用于展示与标识model_namestrproperty使用的 LLM 模型名未设置 LLM 时返回空字符串model_capabilitiesset[ModelCapability] \| Noneproperty模型能力集合未设置 LLM 时为Nonethinkingbool \| Noneproperty当前是否处于思考模式statusStatusSnapshotproperty当前状态快照返回不可变对象hook_engineHookEngineproperty该 Soul 的钩子引擎available_slash_commandslist[SlashCommand[Any]]property该 Soul 支持的斜杠命令列表run(user_input, *, skip_user_prompt_hookFalse)async方法接收用户输入并运行 Agent 循环run方法的行为约定是接收用户输入自然语言或斜杠命令调用持续运行直到达到最大步数或不再有工具调用输入可以是str或list[ContentPart]。方法签名中的skip_user_prompt_hook用于抑制UserPromptSubmit钩子例如后台任务通知这类非用户输入的场景不应被用户配置的 prompt 拦截钩子处理。model_capabilities返回的能力类型定义在 src/kimi_cli/llm.pytype ModelCapability Literal[image_in, video_in, thinking, always_thinking] ALL_MODEL_CAPABILITIES: set[ModelCapability] set(get_args(ModelCapability.__value__))即能力集合包含image_in图像输入、video_in视频输入、thinking思考模式、always_thinking强制思考四种取值ALL_MODEL_CAPABILITIES是全部能力的集合示例直接声明支持全部能力。status属性返回的StatusSnapshot是一个 frozen dataclass定义于 src/kimi_cli/soul/init.pydataclass(frozenTrue, slotsTrue) class StatusSnapshot: context_usage: float # 上下文使用率百分比 yolo_enabled: bool False # 显式 YOLO自动批准开关 afk_enabled: bool False # afk离开键盘模式隐含自动批准 plan_mode: bool False # 计划模式只读研究与规划 context_tokens: int 0 # 当前上下文字符数 max_context_tokens: int 0 # 上下文容量上限 mcp_status: MCPStatusSnapshot | None None # MCP 启动快照Shell 状态栏会读取这些字段进行展示如上下文使用率自定义 Soul 只需返回StatusSnapshot(context_usage0.0)这样的最小快照即可正常工作。EchoSoul 实现逐行拆解main.py 完整实现了上述协议。整体流程是实现EchoSoul→ 构造Shell→ 运行 UI 事件循环。类的属性实现class EchoSoul: def __init__(self) - None: pass property def name(self) - str: return EchoSoul property def model_name(self) - str: return mock property def model_capabilities(self) - set[ModelCapability]: return ALL_MODEL_CAPABILITIES property def status(self) - StatusSnapshot: return StatusSnapshot(context_usage0.0) property def available_slash_commands(self) - list[SlashCommand[Any]]: return []name返回EchoSoul作为该 Agent 的标识model_name返回mockEchoSoul 并不真实调用模型用一个占位模型名即可满足协议model_capabilities直接返回ALL_MODEL_CAPABILITIES声明支持所有能力status返回最小化的StatusSnapshot仅设置context_usage0.0其余字段走默认值available_slash_commands返回空列表——EchoSoul 不注册任何 Soul 级斜杠命令。SlashCommand是一个 frozen dataclass字段为name、description、func、aliases见 src/kimi_cli/utils/slashcmd.pyShell会把 Soul 级命令与 Shell 级命令合并注册见 src/kimi_cli/ui/shell/init.py因此返回空列表并不会让 UI 失去/exit等内置命令。run 方法与 Wire 消息async def run( self, user_input: str | list[ContentPart], *, skip_user_prompt_hook: bool False, ) - None: # skip_user_prompt_hook is part of the Soul protocol but EchoSoul # has no hooks to skip; accept and ignore it for signature compatibility. del skip_user_prompt_hook wire_send(StepBegin(n1)) if isinstance(user_input, str): wire_send(TextPart(textuser_input)) else: for part in user_input: wire_send(part)这是 EchoSoul 的核心逻辑把用户输入原样echo通过 Wire 消息发送给 UI 展示。del skip_user_prompt_hook协议要求该关键字参数但 EchoSoul 没有钩子可跳过为保持签名兼容直接忽略wire_send(StepBegin(n1))发送步骤开始事件。StepBegin的语义是新的 Agent 步骤开始本步骤内的其他事件必须在其之后发送字段n为步骤序号见 src/kimi_cli/wire/types.py。UI 据此渲染步骤进度若输入是字符串包装成TextPart(textuser_input)发送若输入已经是list[ContentPart]如斜杠命令调用转换后的内容则逐个转发。wire_send是 Soul 与 UI 通信的通道定义于 src/kimi_cli/soul/init.pydef wire_send(msg: WireMessage) - None: wire get_wire_or_none() assert wire is not None, Wire is expected to be set when soul is running wire.soul_side.send(msg)它从 ContextVar 中取出当前Wire由run_soul在启动时注入见 src/kimi_cli/soul/init.py然后通过wire.soul_side.send(msg)把消息送入 UI 渲染管线。源码注释称其作用相当于为 Soul 提供的print与input——Soul 应当始终通过该函数发送 Wire 消息而不是直接操作终端。入口把 Soul 交给 Shellif __name__ __main__: soul EchoSoul() ui Shell(soul) asyncio.run(ui.run())Shell类定义于 src/kimi_cli/ui/shell/init.py的构造函数签名是def __init__( self, soul: Soul, welcome_info: list[WelcomeInfoItem] | None None, prefill_text: str | None None, ):Shell持有Soul引用负责渲染 Wire 消息、维护提示符会话、调度 Soul 级与 Shell 级斜杠命令、处理批准请求等。asyncio.run(ui.run())启动整个异步 UI 事件循环。这一行代码正是自定义 Soul 接入 Kimi CLI 终端界面的粘合点。运行效果与 Wire 协议补充启动后Shell 会显示交互式提示符输入任意文本回车EchoSoul 便以第 1 步的形式把你的输入回显到对话流中——这就是一个最小可交互 Agent。如果想要更完整的 Agent 输出可以在run中按协议发送更多 Wire 事件。协议事件均定义在 src/kimi_cli/wire/types.py常见的有事件字段语义TurnBeginuser_input新一轮 Agent 回合开始必须先于该回合其他事件发送types.pyTurnEnd—当前回合结束须在所有事件之后发送回合被中断时可省略types.pyStepBeginn新步骤开始types.pyStepInterrupted—步骤被用户干预或错误中断types.pyStepRetryn, next_attempt, max_attempts, wait_s, ...步骤失败即将重试types.pyCompactionBegin/CompactionEnd—上下文压缩开始/结束须成对出现types.pyHookTriggeredevent, target, hook_count钩子批处理被触发types.pyContentPart及TextPart等消息分片类型从kosong.messagere-export见 src/kimi_cli/wire/types.py包含TextPart、ThinkPart、ImageURLPart、AudioURLPart、VideoURLPart、ToolCallPart等覆盖了文本、思考过程、多模态媒体与工具调用等场景。从 EchoSoul 出发的扩展方向EchoSoul 刻意保持最小但它的骨架可直接扩展为真实 Agent接入真实 LLM在run中调用 Providerkimi_cli.llm.LLM包装了ChatProvider把流式结果转换为TextPart/ThinkPart发送实现状态栏让status返回真实的context_usage、context_tokens等字段Shell 状态栏即会实时展示上下文占用注册斜杠命令构造SlashCommand(name..., description..., func..., aliases...)列表并返回UI 会自动合并 Soul 级命令并支持补全发送工具调用引入ToolCallPart与ToolResult系列消息配合wire_send呈现工具执行过程复用官方调度若需要钩子、批准、后台任务等完整能力可直接继承内置的KimiSoulkimi_cli.soul.agent.Runtime而非从零实现协议。延伸阅读Soul 协议与wire_send/run_soul的完整实现src/kimi_cli/soul/init.pyShell UI 的构造与斜杠命令合并逻辑src/kimi_cli/ui/shell/init.pyWire 消息事件与消息分片类型src/kimi_cli/wire/types.py模型能力枚举与LLM封装src/kimi_cli/llm.pySlashCommand定义src/kimi_cli/utils/slashcmd.py另一个带斜杠命令与工具注册的参考实现examples/custom-tools/基于run_soul直接驱动的流式示例examples/kimi-cli-stream-json/【免费下载链接】kimi-cliKimi Code CLI is your next CLI agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kimi-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考