Iron Gorilla Developers

Define an Agent

Use defineAgent() to declare the purpose, permissions, workflow shape, and triggers of an Iron Gorilla agent.

defineAgent() is the entry point for authoring an Iron Gorilla agent. It describes what the agent is for, what it can access, how it is triggered, and how the run is broken into durable steps.

The point of the definition is clarity. A good agent definition makes it obvious what the agent is allowed to do and what job it owns.

What belongs in the definition

  • identity gives the agent a stable purpose and authority context.
  • tools and data define the governed surface available during execution.
  • triggers describe how work enters the agent.
  • manualInput defines the exact manual-run form and screen order when a person starts the agent.
  • workflow captures the intended action sequence.
  • trust sets the starting posture for the run.
  • steps defines the durable execution boundaries.

A minimal but realistic shape

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

const IntakePayload = z.object({
  customerId: z.string(),
  requestSummary: z.string(),
});

const TriageResult = z.object({
  queue: z.string(),
  priority: z.enum(['low', 'medium', 'high']),
});

export default defineAgent({
  identity: {
    name: 'support_triage',
    scope: 'dept/support',
    authority: 'support-operations',
  },
  tools: ['ticketing'],
  data: {
    permitted: ['support'],
    prohibited: ['PHI'],
    llmExcluded: ['PII'],
  },
  triggers: [{ id: 'manual-entry', type: 'manual', enabled: true }],
  manualInput: {
    fields: {
      customerId: { type: 'string', label: 'Customer ID', required: true },
      requestSummary: {
        type: 'string',
        label: 'Request summary',
      },
    },
    screens: [
      {
        id: 'request',
        title: 'Request',
        fields: ['customerId', 'requestSummary'],
      },
    ],
  },
  workflow: ['triage_request', 'route_ticket'],
  trust: { initialTier: 'medium' },
  steps: [
    step('triage-request', IntakePayload, TriageResult, async (input) => {
      // Read context, classify the request, and return a structured decision.
      return {
        queue: 'billing-review',
        priority: 'medium',
      };
    }),
  ],
});

What customer developers should optimize for

  • A narrow business job instead of a broad assistant.
  • Explicit trigger choices instead of “run somehow.”
  • Minimal tools and data access.
  • Step outputs that are easy for downstream systems or humans to inspect.

Step input context

Each step receives a canonical runtime input object. Manual and webhook object payload fields are copied to the top level of input, and the original trigger payload is always available as input.payload. Primitive payloads are available only as input.payload.

  • input.trigger contains trigger metadata such as id, type, source, and fired time.
  • input.steps contains completed step outputs keyed by step name.
  • input.previous contains the immediately preceding completed step output.
  • input.workflow.completedSteps contains lightweight metadata for completed steps.

The top-level names payload, trigger, steps, previous, and workflow are reserved for the runtime. If a payload object contains one of those fields, the runtime-owned value wins at the top level and the original field remains available under input.payload.

Use those fields when one durable step needs to summarize, transform, or save the output of an earlier step.

Design advice

Treat the definition as a contract, not as incidental setup. If the shape is vague here, the run will be vague in production too.

For manual triggers, keep manualInput literal and simple. The GUI edits this exact block and the API validates manual payloads against it before a job is created.

Supported manualInput leaf fields are string, number, boolean, and select. Fields are optional by default. Add required: true when a run must include a value before it can be queued.

Use select when the operator should choose from a small fixed set of safe modes, such as block vs redact, instead of typing freeform text.

Source-mode agents can also pass dlpPolicy into kernel.callLLM() for per-call DLP behavior. That override is intentionally code-authored today; the visual graph subset does not encode it.

For the exact public types, use the reference:

On this page