Skip to content

Getting Started

A single turn

CliAgent.run is a one-shot: it opens a throwaway session, runs one turn, and returns everything the turn produced.

from agentshim import CliAgent

agent = CliAgent("claude", model="sonnet")
result = agent.run("List the top-level packages.", cwd=".")

print(result.text)
print(result.exit_code, result.duration_ms)

model is an opaque provider-specific string, passed to the CLI unchanged; None leaves the CLI's own default.

Binary lookup and the CLI health check run once, in the constructor, so a broken install fails immediately rather than halfway through a turn.

A conversation

A session resumes the provider's own conversation on every turn after the first.

session = agent.start_session(cwd=".", timeout=600)

session.turn("What does this project do?")
second = session.turn("Which files should I read first?")

assert second.resumed
print(session.session_id)

session.session_id is readable and writable. adopt(session_id) continues a conversation you checkpointed earlier and returns False if the provider cannot resume or a turn is in flight; forget() starts fresh next turn and follows the same rule, returning False rather than racing a live turn.

Per-turn options

Anything that varies per turn goes on a TurnRequest.

from pathlib import Path
from agentshim import OutputSchema, StdioMcpServer, TurnRequest

schema = {
    "type": "object",
    "properties": {"summary": {"type": "string"}},
    "required": ["summary"],
    "additionalProperties": False,
}

result = session.turn(
    TurnRequest(
        prompt="Summarize the failing test.",
        cwd="/workspace",
        timeout=300,
        reasoning_effort="high",
        output_schema=OutputSchema(schema=schema, host_dir=Path("/tmp/schemas")),
        mcp_servers=[StdioMcpServer(name="issues", command="python", args=["-m", "board.mcp"])],
        env={"CI": "1"},
        extra_args=("--append-system-prompt", "Be terse."),
    )
)

print(result.structured_output)

timeout=None means no limit. A request field of None falls back to the session default. Only Claude Code and Codex accept an output schema, and only they accept a reasoning effort; asking any other provider raises ProviderCapabilityError before the process starts. See Providers.

Cancelling

cancel() is thread-safe and can be called from anywhere while a turn is running. It terminates the process group, then kills it after the grace period.

import threading

threading.Timer(30, session.cancel).start()
session.turn("A long-running task.")

Errors

Everything that escapes turn() is an AgentShimError:

from agentshim import CliExitError, CliTimeoutError, SessionResumeError

try:
    session.turn("...")
except SessionResumeError:
    session.forget()          # the conversation is gone; start over
except CliTimeoutError:
    ...                       # the process group has already been killed
except CliExitError as exc:
    print(exc.returncode, exc.stderr)