Iron Gorilla Developers

Autonomous Agents and Loops

Use kernel.agentLoop and defineAutonomousAgent to let a model choose governed tools turn by turn, and know when a deterministic workflow is the better choice.

Iron Gorilla runs agents in two modes. Deterministic workflows (defineAgent with authored steps) are the default: you decide the sequence of actions and the model fills in the language work. Autonomous agents (defineAutonomousAgent) invert that: the model sees a governed tool surface and decides which tools to call, turn by turn, until it reaches the goal.

Both modes run through the same kernel. Every action a model proposes — a tool call, a memory write, another model turn — is still checked by policy, DLP, trust, approvals, metering, and audit before it executes. Autonomy changes who chooses the next action, not who authorizes it.

When to use a loop (and when not to)

Reach for an autonomous agent when the sequence of tools genuinely cannot be scripted ahead of time:

  • open-ended triage or investigation across several tools,
  • "figure out what's wrong and fix it" requests,
  • research that branches based on what each tool returns,
  • anything where you would otherwise write a large hand-rolled if/else over tool results.

Prefer a deterministic workflow when the shape is predictable:

  • gather → decide → act pipelines,
  • scheduled generation, extraction, or transforms,
  • single-call chat replies.

Deterministic workflows are cheaper, faster, and easier to audit because the action sequence is fixed. A loop trades that predictability for flexibility and spends more tokens doing it. If a two-step workflow solves the task, use the workflow.

Choose a loop model, not a label

The managed catalog's Chat label is an upstream model name, not a requirement for Iron Gorilla chat. General and reasoning models can power chat agents. Chat-labeled models remain compatible, but prefer a general or reasoning model for long-running autonomous loops because it is the more appropriate operating profile for multi-turn planning and tool use.

A fully autonomous agent

Example
import { defineAutonomousAgent } from "@forge/sdk";

export default defineAutonomousAgent({
  identity: {
    name: "Support Triage",
    scope: "dept/support",
    authority: "Investigate and resolve inbound support tickets.",
  },
  trust: { initialTier: "medium" },
  triggers: [{ id: "chat-entry", type: "chat", enabled: true }],
  goal: "Resolve the customer's support ticket. Use tools to investigate before answering.",
  loop: {
    providerId: "anthropic",
    model: "claude-sonnet-4-6",
    tools: [
      { name: "search_tickets", ref: { source: "mcp", connectorId: "zendesk", toolId: "search" } },
      { name: "get_ticket", ref: { source: "mcp", connectorId: "zendesk", toolId: "get" } },
      { name: "memory_search", ref: { builtin: "memory_search" } },
    ],
    maxTurns: 16,
    tokenBudget: 200_000,
    maxWallClockMs: 300_000,
  },
});

There are no steps. The platform generates one loop-driving step. For a chat trigger, the latest message and bounded conversation history are folded into the goal automatically, and the chat reply defaults to the loop's final answer — you do not need formatChatTranscript or a chatOutput selector.

The tool surface is server-authoritative

The loop.tools you declare is a request, not the final list. At runtime the platform intersects it with the live connector catalog and runs a policy dry-run per tool:

  • tools the org's policy would deny are removed before the model sees them,
  • tools gated by require_approval are shown with an approval annotation, and calling one pauses the run durably for a human decision, then resumes,
  • built-in memory_search / memory_write are fenced to the agent's allowed memory scopes.

The model only ever names a tool. The runtime resolves the name to the signed connector target, so a compromised prompt cannot conjure a tool that was not declared and approved.

Caps: how long can a loop run?

Always set caps. They are enforced server-side, so a runaway or manipulated model cannot exceed them:

CapFieldDefaultBehavior at the limit
TurnsmaxTurns24 (max 128)Loop forces a final answer turn
TokenstokenBudgetnoneLoop wraps up near 90% of budget
Wall clockmaxWallClockMsnoneLoop wraps up near 90%; kernel backstop past the ceiling

When a cap nears, the loop is asked for its best final answer rather than being cut off mid-thought. Per-turn finance gates and quota reservations also apply to every model turn, so an autonomous agent is bounded by your existing spend controls in addition to these caps.

Hybrid: a loop inside a workflow

When only part of a workflow is open-ended, call kernel.agentLoop from inside a deterministic step. The rest of the workflow stays scripted; the loop handles the exploratory part.

Example
import { defineAgent, kernel, step } from "@forge/sdk";
import { z } from "zod";

export default defineAgent({
  identity: { name: "Incident Assistant", scope: "dept/ops", authority: "Assist on-call." },
  trust: { initialTier: "medium" },
  triggers: [{ id: "manual-entry", type: "manual", enabled: true }],
  // The agent config still declares the loop tool surface; the step-level call
  // may narrow it but never widen it.
  loop: {
    providerId: "anthropic",
    model: "claude-sonnet-4-6",
    tools: [
      { name: "query_logs", ref: { source: "mcp", connectorId: "datadog", toolId: "query" } },
    ],
    maxTurns: 8,
  },
  steps: [
    step(
      "investigate",
      z.object({ incidentId: z.string() }),
      z.object({ finalText: z.string(), stopReason: z.string() }),
      async (input) => {
        const result = await kernel.agentLoop({
          goal: `Investigate incident ${input.incidentId} and summarize the likely root cause.`,
          providerId: "anthropic",
          model: "claude-sonnet-4-6",
          tools: ["query_logs"],
          maxTurns: 8,
        });
        return { finalText: result.finalText, stopReason: result.stopReason };
      },
    ),
  ],
});

How chat differs from a loop

The built-in chat experience for a deterministic agent is effectively a scripted single turn: the runtime injects the transcript, calls the model once through kernel.callLLM, and returns the reply. An autonomous chat agent replaces that single turn with a governed loop — the model can call tools across several turns before replying — while chat continuity (latest message plus bounded history) is still handled for you. Use a deterministic chat agent when a single reasoned reply is enough; use an autonomous chat agent when the reply requires the model to go investigate first.

To add governed realtime speech to an autonomous chat agent, continue with Voice agents. The speech model is separate from the loop model, while the same signed tool surface and runtime controls continue to apply.

To configure inherited recall and built-in memory tools, read Scoped memory.

Governance and enablement

Autonomous mode is gated by the organization's autonomous_loops capability, which ships off by default. An admin enables it deliberately before any agent can run a loop. Everything else — policy rules, DLP, approvals, memory scoping, trust — behaves exactly as it does for workflow agents, because loop actions are ordinary kernel actions.

A loop that calls tools based on tool results introduces prompt-injection risk: fetched content can try to steer the model. Iron Gorilla scans tool results with DLP before they reach the model, wraps them in untrusted-content markers, and lets you write policy rules that require approval for egress after an untrusted read. Mediation stops an injected instruction from succeeding, but the model can still be asked; keep destructive or egress-capable loop tools behind approval.

What operators see

An autonomous run appears in Run Details as an "Autonomous loop" section grouped into "Turn N" blocks: each turn shows the model turn with its token and cost, followed by the tool calls it made with their governance decisions. Approval pauses render inline exactly as they do for workflow agents.

On this page