Skip to main content
The Python SDK gives you the same control as the TypeScript SDK from Python code: start Threads, run Turns, stream events, and resume Sessions.Every Turn runs one local mcode exec --output-format=stream-json process and continues the Session with --session. The package is 0.x, so APIs may change between minor versions until 1.0.Related pages: TypeScript SDK, Headless and CI. Package: PyPI minimax-code-sdk.

Requirements

The SDK does not install the CLI. Install it separately and sign in, or configure a working API-key provider in the data directory, before the first run.

Installation

Import the package as minimax_code.

Quick start

run() returns a Turn only when the status is succeeded. It carries final_response, normalized items, usage, model, session_id, turn_id, duration_ms, and the full CLI result. Every other outcome raises.

Blocking API

If your code is not async, use SyncMCode. It has the same methods without await:
SyncMCode runs its own event loop, so it cannot be used where a loop is already running, such as a Jupyter notebook or inside an async def function. There, running a Turn raises a single RuntimeError that points you to the async API. Use MCode with await instead.

CLI resolution

Lookup order:
  1. MCodeOptions(bin=...);
  2. The MCODE_BIN environment variable;
  3. mcode on PATH.
The SDK never starts the CLI through a shell. A missing CLI raises MCodeNotFoundError. Before the first run, each client runs mcode --version once; a CLI older than 0.6.3 raises MCodeVersionError.On Windows, the mcode.cmd launcher written by the official installer or by npm / pnpm is followed to the JS entry and Node runtime it runs. An unrecognized .cmd file is rejected; pass the JS entry as bin instead.

Options

Options are dataclasses passed to the client, the Thread, and each Turn.

MCode(MCodeOptions(...))

To add variables instead of replacing the environment, merge os.environ:

start_thread / resume_thread(ThreadOptions(...))

Invalid values raise MCodeInvocationError before the CLI starts. mode="lightweight" on resume_thread is rejected the same way. There is no ask permission: each Turn is a separate process, so interactive permission prompts are not supported.

thread.run / thread.run_streamed(prompt, RunOptions(...))

A Thread runs one Turn at a time. A concurrent call raises ThreadBusyError; Turns are not queued.

Threads and resume

thread.id is the Session id. It becomes available once the first Turn emits its first event. Persist it and continue later with resume_thread:
A Session belongs to the workspace it was created in, so pass the same cwd to resume_thread(). When cwd is omitted, the current working directory at that call is used. A Thread pins its cwd when it is created, so a later os.chdir() does not affect it. Resuming from a different workspace fails with MCodeRunError, and retrying does not help.

Streaming

run_streamed() returns a StreamedTurn that you iterate with async for. Text deltas for an agent_message can arrive on item.started as well as item.updated, so read contentDelta from any event that carries an item:
Events are the CLI’s stream-json events as plain dicts, passed through unchanged, unknown types included: exec.started, session.started / session.resumed, turn.started, item.started / item.updated / item.completed, turn.completed, turn.failed, and exec.completed. The one exception: an item.updated snapshot (no contentDelta) identical to the previous snapshot of the same item is skipped. Text deltas are never skipped.turn.failed is an ordinary event. Iteration raises only for process or protocol failures.Turn.items are normalized dataclasses: AgentMessageItem, ReasoningItem, and ToolCallItem. Items that had no item.completed when the Turn ended have incomplete=True.

Errors

Every error subclasses MCodeError, which carries exit_code, stderr (the CLI stderr tail, for diagnostics only), session_id, result, and items.MCodeRunError.status is failed, timeout, or limit_exceeded. category is config, runtime, internal, or None. MCODE_EXEC_EXIT_CODES maps the CLI exit codes by name.
The SDK never retries automatically. When an error carries session_id, you can continue with resume_thread(error.session_id, ...). Errors can be pickled, for example to return them from a ProcessPoolExecutor worker.

Cancellation and timeouts

  • streamed.cancel() sends SIGTERM, the CLI’s cancel signal. The stream then ends with the CLI’s final events;
  • Leaving the async for early (break or an exception), or cancelling the task running thread.run(), stops the CLI: SIGTERM, then SIGKILL if it is still running after the CLI’s 60-second shutdown budget. The next Turn on the same Thread waits for that shutdown instead of raising ThreadBusyError;
  • async with streamed: or await streamed.aclose() stops the CLI deterministically;
  • timeout_ms is enforced by the CLI. If the CLI is still running 90 seconds after timeout_ms, the SDK kills it and raises MCodeRunError with status="timeout";
  • On Windows, cancellation stops the CLI immediately.

Not available yet

  • Interactive permission prompts (permission="ask") and custom in-process tools;
  • output_schema (structured-output constraints), approval callbacks, steering a running Turn, and forking.
For direct CLI usage or structured output, see Headless and CI.