# How to Manage Step Limits for Agents in OpenClaude: A Complete Guide

> Learn how to manage agent step limits in OpenClaude. Configure maxSteps to enforce limits and generate summaries automatically for efficient agent control.

- Repository: [Gitlawb/openclaude](https://github.com/Gitlawb/openclaude)
- Tags: how-to-guide
- Published: 2026-09-05

---

**OpenClaude caps agent tool-use actions by configuring an `agentStepLimit` object with a `maxSteps` value, which triggers automatic enforcement and summary generation when the ceiling is reached.**

The Gitlawb/openclaude repository provides built-in safeguards to prevent runaway agent loops through deterministic step limiting. By configuring **agent step limits**, you establish a hard ceiling on tool invocations per query, ensuring predictable resource consumption and forcing concise final summaries when budgets exhaust.

## Understanding Agent Step Limits

Agent step limits in OpenClaude function as a protective boundary around tool-use operations. Rather than allowing an agent to invoke tools indefinitely, the system tracks each execution against a configured maximum and halts further processing once the threshold is reached.

This mechanism delivers three critical guarantees:

- **Safety** – Prevents infinite loops that could exhaust API quotas or hang CLI sessions.
- **Predictability** – Establishes an upper bound on LLM-driven tool calls for cost control.
- **Deterministic summarization** – Forces the model to generate a final answer without additional tool invocations once the budget depletes.

## Configuring Step Limits at Query Time

To enable step limiting, pass an **`agentStepLimit`** object when initializing a query. This configuration undergoes normalization before execution begins.

### The `agentStepLimit` Object Structure

The configuration accepts two properties:

- **`maxSteps`** (required integer) – The absolute maximum number of tool calls permitted.
- **`agentType`** (optional string) – A classifier for the agent variant (e.g., `'general-purpose'`, `'explorer'`).

If `maxSteps` is omitted, non-integer, or less than or equal to zero, the system ignores the limit entirely.

### Normalization Logic

The function `normalizeAgentStepLimit` in [`src/query.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/query.ts) validates and sanitizes the input configuration. This ensures that only valid integer ceilings propagate through the execution pipeline, preventing malformed configurations from causing runtime errors.

```typescript
import { OpenClaude } from '@gitlawb/openclaude/sdk';

const client = new OpenClaude({ apiKey: process.env.OPENCLAUDE_API_KEY });

const response = await client.query({
  prompt: 'Analyze this repository and list its major components.',
  agentStepLimit: { maxSteps: 4, agentType: 'general-purpose' },
});

```

## Runtime Enforcement and State Tracking

Once normalized, OpenClaude instantiates an **`AgentStepLimitState`** object that persists alongside the query context. This state tracks the remaining budget and enforcement flags throughout the execution lifecycle.

### State Management

The state object maintains three key fields:

- **`maxSteps`** – The configured ceiling from initialization.
- **`stepsUsed`** – A counter incrementing with each tool execution.
- **`summaryRequested`** – A boolean flag set when the limit triggers.

The main query loop updates this state every iteration around line 2678 in [`src/query.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/query.ts), ensuring real-time accuracy as tool calls dispatch.

### Enforcement Checks

Before each batch of tool calls executes, the system evaluates:

```typescript
if (agentStepLimit && agentStepLimit.summaryRequested) {
  // stop executing further tools
}

```

If the remaining steps (calculated as `maxSteps - stepsUsed`) are insufficient for the upcoming batch, the limit activates immediately.

## Synthetic Tool Result Generation

When the step limit triggers, OpenClaude synthesizes a specialized tool-result message rather than allowing a partial execution. The helper function `createAgentStepLimitToolResult` in [`src/query.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/query.ts) constructs this payload.

### Message Structure

The synthetic result contains:

- A fixed prefix **`Agent step limit reached`** (defined in [`src/query/agentStepLimit.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/query/agentStepLimit.ts)).
- The agent identifier and progress counter (e.g., `(3/5 tool uses)`).
- Instructions directing the LLM to cease tool use and return a final summary.

The resulting `UserMessage` carries the flag `isAgentStepLimitToolResult: true`, enabling downstream logic to distinguish synthetic limits from genuine tool failures.

## Summary Request Handling

After limit activation, the function `createAgentStepLimitSummaryRequest` emits a final system message. This notification explicitly informs the model that the agent reached its configured step limit after exhausting the tool-use budget, compelling the LLM to produce a concluding answer without further tool invocations.

You can programmatically detect this condition by inspecting response messages:

```typescript
if (response.toolResults?.some(r => r.content?.startsWith('Agent step limit reached'))) {
  console.log('Step limit triggered – final summary follows.');
}

```

## Propagation to Sub-Agents

Step limits cascade through agent hierarchies automatically. When a parent agent spawns a sub-agent via the `AgentTool` execution path, the configuration propagates through [`src/tools/AgentTool/runAgent.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/tools/AgentTool/runAgent.ts) at line 832.

This inheritance ensures that nested calls respect the same budget constraints as their parent, preventing sub-agents from circumventing limits through delegation.

### Sub-Agent Configuration Example

```typescript
await client.query({
  prompt: 'Run a sub-agent to explore the file tree.',
  agentStepLimit: { maxSteps: 2, agentType: 'explorer' },
});

```

The sub-agent stops after two tool calls and returns a summary of its exploration, regardless of whether additional work remains pending.

## Summary

Managing agent step limits in OpenClaude requires understanding the configuration interface, runtime state machine, and message synthesis pipeline:

- Pass an **`agentStepLimit`** object with a valid **`maxSteps`** integer to activate limiting.
- The system normalizes input via `normalizeAgentStepLimit` in [`src/query.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/query.ts) and tracks usage through `AgentStepLimitState`.
- When limits trigger, `createAgentStepLimitToolResult` generates synthetic messages marked with `isAgentStepLimitToolResult: true`.
- Sub-agents automatically inherit limits through [`src/tools/AgentTool/runAgent.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/tools/AgentTool/runAgent.ts).

## Frequently Asked Questions

### What happens if I provide an invalid `maxSteps` value?

If `maxSteps` is missing, not an integer, or less than or equal to zero, the `normalizeAgentStepLimit` function in [`src/query.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/query.ts) disregards the configuration entirely. The query executes without step limiting, allowing unlimited tool invocations.

### Do sub-agents inherit step limits from parent agents?

Yes. The limit configuration propagates automatically through the `AgentTool` execution path at line 832 in [`src/tools/AgentTool/runAgent.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/tools/AgentTool/runAgent.ts). Sub-agents receive the same `maxSteps` ceiling and enforce it independently against their own tool usage.

### How can I detect when a step limit was triggered programmatically?

Inspect the response's `toolResults` array for entries where `content` starts with the string `Agent step limit reached` (defined in [`src/query/agentStepLimit.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/query/agentStepLimit.ts)). Alternatively, check for the boolean flag `isAgentStepLimitToolResult: true` on message objects to identify synthetic limit notifications.