> ## Documentation Index
> Fetch the complete documentation index at: https://docs.overcut.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Event Context Reference

> Complete reference of all event context properties available in Overcut workflows for building dynamic automations.

Event context provides access to all information about the event that triggered your workflow. You can use this data throughout your workflow using template variables like `{{trigger.issue.title}}` or `{{trigger.repository.fullName}}`.

<Note>
  All event properties are **platform-agnostic**: they work consistently whether your event comes from GitHub, GitLab, Jira, Bitbucket, Azure DevOps, or ClickUp. Overcut automatically normalizes platform-specific data into this standardized format.
</Note>

***

## Template Variable Syntax

Access event context properties using double curly braces:

```handlebars theme={null}
{{trigger.issue.title}}
{{trigger.repository.fullName}}
{{trigger.pullRequest.headBranch}}
{{trigger.actor.login}}
```

You can use these template variables in:

* Agent instructions
* Action parameters
* Conditional logic
* Step outputs

***

## Inspect context for a run

This page describes the context shape available to workflow templates. To inspect the actual values for one workflow run, open the run details and select **Context** to open the **Run Context** panel.

The panel shows read-only JSON with the run's `trigger` data and `outputs` from completed steps. Use it to confirm the values behind template expressions such as `{{trigger.issue.title}}` and `{{outputs.<stepId>.<field>}}`. Step outputs update while the run executes.

***

## Base Event Properties

These properties are available for **all event types**:

### Event Metadata

<ParamField path="trigger.eventType" type="string">
  The standardized event type that triggered the workflow (e.g., `issue_opened`, `pull_request_merged`, `mention`).

  **Example:** `{{trigger.eventType}}`
</ParamField>

<ParamField path="trigger.triggerObjectName" type="string">
  Human-readable name of the object that triggered the event.

  **Example:** `{{trigger.triggerObjectName}}`
</ParamField>

<ParamField path="trigger.triggerObjectNumber" type="string">
  Number or identifier of the triggering object (issue number, PR number, etc.).

  **Example:** `{{trigger.triggerObjectNumber}}`
</ParamField>

<ParamField path="trigger.triggerObjectUrl" type="string">
  Direct URL to the triggering object in the source platform.

  **Example:** `{{trigger.triggerObjectUrl}}`
</ParamField>

### Repository Context

<ParamField path="trigger.repository.name" type="string">
  Repository name (e.g., `"blog-server"`).

  **Example:** `{{trigger.repository.name}}`
</ParamField>

<ParamField path="trigger.repository.fullName" type="string">
  Full repository name including owner (e.g., `"acme/blog-server"`).

  **Example:** `{{trigger.repository.fullName}}`
</ParamField>

<ParamField path="trigger.repository.owner" type="string">
  Repository owner username or organization name.

  **Example:** `{{trigger.repository.owner}}`
</ParamField>

<ParamField path="trigger.repository.url" type="string">
  Clone URL for the repository.

  **Example:** `{{trigger.repository.url}}`
</ParamField>

<ParamField path="trigger.repository.defaultBranch" type="string">
  Default branch name (e.g., `"main"`, `"master"`).

  **Example:** `{{trigger.repository.defaultBranch}}`
</ParamField>

<ParamField path="trigger.repository.provider" type="string">
  Git provider name (e.g., `"github"`, `"gitlab"`, `"bitbucket"`).

  **Example:** `{{trigger.repository.provider}}`
</ParamField>

### Actor Context

The user or bot that triggered the event.

<ParamField path="trigger.actor.login" type="string">
  Username or login of the actor.

  **Example:** `{{trigger.actor.login}}`
</ParamField>

<ParamField path="trigger.actor.name" type="string">
  Display name of the actor.

  **Example:** `{{trigger.actor.name}}`
</ParamField>

<ParamField path="trigger.actor.email" type="string">
  Email address of the actor (if available).

  **Example:** `{{trigger.actor.email}}`
</ParamField>

<ParamField path="trigger.actor.type" type="string">
  Type of actor: `"User"`, `"Bot"`, or `"Organization"`.

  **Example:** `{{trigger.actor.type}}`
</ParamField>

### Organization Context

Available when the repository belongs to an organization.

<ParamField path="trigger.organization.login" type="string">
  Organization username or login.

  **Example:** `{{trigger.organization.login}}`
</ParamField>

<ParamField path="trigger.organization.name" type="string">
  Organization display name.

  **Example:** `{{trigger.organization.name}}`
</ParamField>

***

## Issue Event Properties

Available for issue-related events: `issue_opened`, `issue_closed`, `issue_edited`, `issue_assigned`, `issue_unassigned`, `issue_labeled`, `issue_unlabeled`, `issue_commented`.

### Core Issue Properties

<ParamField path="trigger.issue.number" type="number">
  Issue number (unique within the repository).

  **Example:** `{{trigger.issue.number}}`
</ParamField>

<ParamField path="trigger.issue.title" type="string">
  Issue title.

  **Example:** `{{trigger.issue.title}}`

  <Note>**ClickUp**: For non-creation events, the task title may not be included in the webhook payload. `trigger.issue.title` may be empty in these cases.</Note>
</ParamField>

<ParamField path="trigger.issue.state" type="string">
  Current state of the issue: `"open"` or `"closed"`.

  **Example:** `{{trigger.issue.state}}`
</ParamField>

<ParamField path="trigger.issue.body" type="string">
  Issue description or body content.

  **Example:** `{{trigger.issue.body}}`
</ParamField>

<ParamField path="trigger.issue.author" type="string">
  Username of the issue author.

  **Example:** `{{trigger.issue.author}}`
</ParamField>

### Issue Metadata

<ParamField path="trigger.issue.labels" type="array<string>">
  Array of label names attached to the issue.

  **Example:** `{{trigger.issue.labels}}` or `{{trigger.issue.labels.[0]}}` for first label
</ParamField>

<ParamField path="trigger.issue.assignees" type="array<string>">
  Array of usernames assigned to the issue.

  **Example:** `{{trigger.issue.assignees}}` or `{{trigger.issue.assignees.[0]}}`
</ParamField>

<ParamField path="trigger.issue.milestone" type="string">
  Milestone title if the issue is assigned to a milestone.

  **Example:** `{{trigger.issue.milestone}}`
</ParamField>

<ParamField path="trigger.issue.workItemType" type="string">
  Normalized issue type coming from the source tracker (e.g., `"Bug"`, `"Task"`, `"Story"`). Use this to branch workflows by work item type without writing provider-specific logic.

  **Example:** `{{trigger.issue.workItemType}}`

  <Note>**GitHub** issues may return an empty string because the platform does not classify issues, while Jira, GitLab, and Azure DevOps provide their native issue types.</Note>
</ParamField>

<ParamField path="trigger.issue.confidential" type="boolean">
  Whether the issue is confidential.

  **Example:** `{{trigger.issue.confidential}}`

  <Note>**GitLab only** - This property is only available for GitLab issues. Returns `undefined` for other providers.</Note>
</ParamField>

### Status Transition Fields

<ParamField path="trigger.statusFrom" type="string">
  Previous status name for a status transition. Use this value to target a specific change, such as moving from "Backlog" to "In Progress".

  **Example:** `{{trigger.statusFrom}}`

  <Note>
    **Provider availability:** Jira, Azure DevOps, and ClickUp include the previous status for state change events. Linear does not include the prior status, so `trigger.statusFrom` is undefined for Linear transitions.
  </Note>
</ParamField>

<ParamField path="trigger.statusTo" type="string">
  New status name after the transition. The value matches the label shown in your tracker.

  **Example:** `{{trigger.statusTo}}`

  <Note>
    **Provider availability:** Jira, Azure DevOps, Linear, and ClickUp supply the destination status for state change events. These fields are empty for issue events that only provide open or closed state without transition details.
  </Note>
</ParamField>

### Issue Timestamps

<ParamField path="trigger.issue.createdAt" type="string">
  ISO timestamp when the issue was created.

  **Example:** `{{trigger.issue.createdAt}}`
</ParamField>

<ParamField path="trigger.issue.updatedAt" type="string">
  ISO timestamp when the issue was last updated.

  **Example:** `{{trigger.issue.updatedAt}}`
</ParamField>

<ParamField path="trigger.issue.closedAt" type="string">
  ISO timestamp when the issue was closed (if applicable).

  **Example:** `{{trigger.issue.closedAt}}`
</ParamField>

***

## Pull Request Event Properties

Available for PR-related events: `pull_request_opened`, `pull_request_closed`, `pull_request_merged`, `pull_request_edited`, `pull_request_reviewed`, `pull_request_assigned`, `pull_request_unassigned`, `pull_request_labeled`, `pull_request_unlabeled`, `pull_request_commented`, `pull_request_review_commented`.

<ParamField path="trigger.commitAdded" type="boolean">
  <strong>Whether the event was caused by new commits being pushed to the pull request.</strong>

  * Always `true` for `pull_request_opened` events (initial commit set).
  * `true` for `pull_request_edited` **only** when the edit originates from new commits.
  * `false` for metadata-only changes such as title/body edits, label updates, or reviewer requests.

  Use this flag in trigger conditions to run workflows exclusively on code-changing updates.

  <Note>**GitLab and GitHub only** - This property is only available for GitLab and GitHub pull requests. Returns `false` for other providers.</Note>
</ParamField>

<ParamField path="trigger.prAction" type="string">
  Normalized action describing the latest change detected on the pull request. Use it to filter workflows based on the specific action that occurred.

  **Available values:**

  * `opened` — the pull request was created.
  * `closed` — the pull request was closed without merging.
  * `merged` — the pull request was merged.
  * `reopened` — a previously closed pull request was reopened.
  * `ready_for_review` — the author (or maintainer) marked a draft pull request ready for review.
  * `converted_to_draft` — the pull request was converted to a draft.

  <Note>**Provider support:** `opened`, `closed`, and `merged` are available across all providers. `reopened` is supported on GitHub, GitLab, and Azure DevOps. Draft transitions (`ready_for_review`, `converted_to_draft`) are available on GitHub, GitLab, and Azure DevOps only. Bitbucket does not support draft pull requests.</Note>
</ParamField>

<ParamField path="trigger.prState" type="string">
  Normalized state of the pull request at the time of the event. Values are `opened`, `closed`, or `merged`, regardless of the underlying provider terminology.

  <Note>Use this field to distinguish lifecycle changes (closed vs. merged) while `trigger.prAction` captures the precise activity that fired the webhook.</Note>
</ParamField>

<Warning>
  **Provider Differences**: While all core properties (number, title, state, branches, labels, assignees) are available across all providers, some advanced properties like change statistics, merge status, and reviewer information are provider-specific. Check the individual property notes below for availability.
</Warning>

### Core Pull Request Properties

<ParamField path="trigger.pullRequest.number" type="number">
  Pull request number.

  **Example:** `{{trigger.pullRequest.number}}`
</ParamField>

<ParamField path="trigger.pullRequest.title" type="string">
  Pull request title.

  **Example:** `{{trigger.pullRequest.title}}`
</ParamField>

<ParamField path="trigger.pullRequest.state" type="string">
  Current state: `"open"`, `"closed"`, or `"merged"`.

  **Example:** `{{trigger.pullRequest.state}}`
</ParamField>

<ParamField path="trigger.pullRequest.body" type="string">
  Pull request description or body content.

  **Example:** `{{trigger.pullRequest.body}}`
</ParamField>

<ParamField path="trigger.pullRequest.author" type="string">
  Username of the pull request author.

  **Example:** `{{trigger.pullRequest.author}}`
</ParamField>

### Branch Information

<ParamField path="trigger.pullRequest.baseBranch" type="string">
  Target branch name (where the PR will be merged into).

  **Example:** `{{trigger.pullRequest.baseBranch}}`
</ParamField>

<ParamField path="trigger.pullRequest.headBranch" type="string">
  Source branch name (the branch with changes).

  **Example:** `{{trigger.pullRequest.headBranch}}`
</ParamField>

<ParamField path="trigger.pullRequest.baseSha" type="string">
  Base commit SHA.

  **Example:** `{{trigger.pullRequest.baseSha}}`

  <Note>**Not available on GitLab** - GitLab webhooks don't include the base SHA (would require an additional API call).</Note>
</ParamField>

<ParamField path="trigger.pullRequest.headSha" type="string">
  Head commit SHA.

  **Example:** `{{trigger.pullRequest.headSha}}`
</ParamField>

<ParamField path="trigger.pullRequest.mergeCommitSha" type="string">
  Merge commit SHA (available after merge).

  **Example:** `{{trigger.pullRequest.mergeCommitSha}}`
</ParamField>

### Pull Request Metadata

<ParamField path="trigger.pullRequest.labels" type="array<string>">
  Array of label names attached to the pull request.

  **Example:** `{{trigger.pullRequest.labels}}`
</ParamField>

<ParamField path="trigger.pullRequest.assignees" type="array<string>">
  Array of assignee usernames.

  **Example:** `{{trigger.pullRequest.assignees}}`
</ParamField>

<ParamField path="trigger.pullRequest.requestedReviewers" type="array<string>">
  Array of requested reviewer usernames.

  **Example:** `{{trigger.pullRequest.requestedReviewers}}`

  <Note>**GitHub only** - GitLab returns an empty array (no explicit reviewer request concept). Not available on Bitbucket or Azure DevOps.</Note>
</ParamField>

<ParamField path="trigger.pullRequest.milestone" type="string">
  Milestone title if assigned.

  **Example:** `{{trigger.pullRequest.milestone}}`
</ParamField>

<ParamField path="trigger.pullRequest.draft" type="boolean">
  Whether the pull request is a draft.

  **Example:** `{{trigger.pullRequest.draft}}`
</ParamField>

### Change Statistics

<Note>**GitHub only** - Change statistics (additions, deletions, changedFiles) are only available for GitHub pull requests. Other providers don't include these metrics in their webhook payloads.</Note>

<ParamField path="trigger.pullRequest.additions" type="number">
  Number of lines added.

  **Example:** `{{trigger.pullRequest.additions}}`
</ParamField>

<ParamField path="trigger.pullRequest.deletions" type="number">
  Number of lines deleted.

  **Example:** `{{trigger.pullRequest.deletions}}`
</ParamField>

<ParamField path="trigger.pullRequest.changedFiles" type="number">
  Number of files changed.

  **Example:** `{{trigger.pullRequest.changedFiles}}`
</ParamField>

### Merge Status

<ParamField path="trigger.pullRequest.mergeable" type="boolean | null">
  Whether the pull request can be merged (null if unknown).

  **Example:** `{{trigger.pullRequest.mergeable}}`

  <Note>**GitHub and GitLab only** - Not available on Bitbucket or Azure DevOps.</Note>
</ParamField>

<ParamField path="trigger.pullRequest.rebaseable" type="boolean | null">
  Whether the pull request can be rebased (null if unknown).

  **Example:** `{{trigger.pullRequest.rebaseable}}`

  <Note>**GitHub only** - Not available on other providers.</Note>
</ParamField>

<ParamField path="trigger.pullRequest.autoMerge" type="boolean">
  Whether auto-merge is enabled.

  **Example:** `{{trigger.pullRequest.autoMerge}}`

  <Note>**GitHub only** - Not available on other providers.</Note>
</ParamField>

### Pull Request Timestamps

<ParamField path="trigger.pullRequest.createdAt" type="string">
  ISO timestamp when the pull request was created.

  **Example:** `{{trigger.pullRequest.createdAt}}`
</ParamField>

<ParamField path="trigger.pullRequest.updatedAt" type="string">
  ISO timestamp when the pull request was last updated.

  **Example:** `{{trigger.pullRequest.updatedAt}}`
</ParamField>

<ParamField path="trigger.pullRequest.closedAt" type="string">
  ISO timestamp when the pull request was closed (if applicable).

  **Example:** `{{trigger.pullRequest.closedAt}}`
</ParamField>

<ParamField path="trigger.pullRequest.mergedAt" type="string">
  ISO timestamp when the pull request was merged (if applicable).

  **Example:** `{{trigger.pullRequest.mergedAt}}`
</ParamField>

***

## CI Workflow Event Properties

Available for CI workflow events: `ci_workflow_queued`, `ci_workflow_started`, `ci_workflow_completed`, `ci_workflow_failed`, `ci_workflow_cancelled`, `ci_workflow_timed_out`.

<Warning>
  Pull request context (`trigger.pullRequest.*`) is only populated when `trigger.ciWorkflow.isPullRequest` is `true`. The fields available vary by provider. See [Pull Request Context in CI Events](#pull-request-context-in-ci-events) for details.
</Warning>

### Run Identity

<ParamField path="trigger.ciWorkflow.runId" type="string">
  Unique identifier for the CI run, as assigned by the provider.

  **Example:** `{{trigger.ciWorkflow.runId}}`
</ParamField>

<ParamField path="trigger.ciWorkflow.workflowName" type="string">
  Name of the pipeline or workflow that executed.

  **Example:** `{{trigger.ciWorkflow.workflowName}}`
</ParamField>

<ParamField path="trigger.ciWorkflow.workflowUrl" type="string">
  URL to view the run in the CI provider's UI.

  **Example:** `{{trigger.ciWorkflow.workflowUrl}}`

  <Note>Optional: not every provider includes a direct link in its webhook payload.</Note>
</ParamField>

### Status and Outcome

<ParamField path="trigger.ciWorkflow.status" type="string">
  Normalized run status. One of: `Queued`, `InProgress`, `Succeeded`, `Failed`, `Cancelled`, `TimedOut`.

  **Example:** `{{trigger.ciWorkflow.status}}`
</ParamField>

<ParamField path="trigger.ciWorkflow.conclusion" type="string">
  Raw, provider-specific conclusion value (e.g., GitHub's `action_required` or GitLab's `manual`). Use `status` for cross-provider logic and `conclusion` when you need provider-level detail.

  **Example:** `{{trigger.ciWorkflow.conclusion}}`

  <Note>Optional: only present on terminal-state events (`ci_workflow_completed`, `ci_workflow_failed`, `ci_workflow_cancelled`, `ci_workflow_timed_out`).</Note>
</ParamField>

### Source Context

<ParamField path="trigger.ciWorkflow.branch" type="string">
  The branch that triggered the CI run.

  **Example:** `{{trigger.ciWorkflow.branch}}`
</ParamField>

<ParamField path="trigger.ciWorkflow.commitSha" type="string">
  The commit SHA that the CI run executed against.

  **Example:** `{{trigger.ciWorkflow.commitSha}}`
</ParamField>

<ParamField path="trigger.ciWorkflow.isPullRequest" type="boolean">
  Whether the CI run is associated with a pull request. When `true`, `trigger.pullRequest.*` fields are available.

  **Example:** `{{trigger.ciWorkflow.isPullRequest}}`
</ParamField>

<ParamField path="trigger.ciWorkflow.pullRequestId" type="number">
  Pull request number when the run is PR-associated.

  **Example:** `{{trigger.ciWorkflow.pullRequestId}}`

  <Note>Optional: only present when `trigger.ciWorkflow.isPullRequest` is `true`.</Note>
</ParamField>

### Pull Request Context in CI Events

<Note>
  When a CI run is associated with a pull request, `trigger.pullRequest.*` fields are populated, but what is available depends on the provider:

  * **GitHub Actions**: PR number and branch names are available; title is not included in the webhook payload.
  * **GitLab CI**: Full merge request data is only available on MR-triggered pipelines. Add a `merge_request_event` rule to your `.gitlab-ci.yml` to ensure MR context is sent.
  * **Azure DevOps**: PR ID and branch names are available; title is not included.
  * **Bitbucket Pipelines**: Full PR context including title is available.

  When available, these fields follow the same schema as [Pull Request Event Properties](#pull-request-event-properties) above.
</Note>

### Timing

<ParamField path="trigger.ciWorkflow.queuedAt" type="string">
  ISO timestamp when the run was queued.

  **Example:** `{{trigger.ciWorkflow.queuedAt}}`

  <Note>Optional: not available on Azure DevOps.</Note>
</ParamField>

<ParamField path="trigger.ciWorkflow.startedAt" type="string">
  ISO timestamp when the run started executing.

  **Example:** `{{trigger.ciWorkflow.startedAt}}`

  <Note>Optional: not present for `ci_workflow_queued` events.</Note>
</ParamField>

<ParamField path="trigger.ciWorkflow.completedAt" type="string">
  ISO timestamp when the run finished.

  **Example:** `{{trigger.ciWorkflow.completedAt}}`

  <Note>Optional: only present on terminal-state events.</Note>
</ParamField>

<ParamField path="trigger.ciWorkflow.duration" type="number">
  Run duration in milliseconds.

  **Example:** `{{trigger.ciWorkflow.duration}}`

  <Note>Optional: only present on terminal-state events when both start and end times are known.</Note>
</ParamField>

### Additional Fields

<ParamField path="trigger.ciWorkflow.jobCount" type="number">
  Total number of jobs in the pipeline.

  **Example:** `{{trigger.ciWorkflow.jobCount}}`

  <Note>**GitLab only**: other providers do not include job count in their webhook payloads.</Note>
</ParamField>

***

## Action-Specific Context

These properties provide additional context about the specific action that triggered the event.

### Label Operations

Available for `issue_labeled`, `issue_unlabeled`, `pull_request_labeled`, `pull_request_unlabeled` events. The `labelsAdded` / `labelsRemoved` arrays are also populated on `issue_edited` for providers without a discrete label event (see the Azure DevOps note below).

<ParamField path="trigger.label" type="string">
  The label that was added or removed. When several labels change at once this is the **first added** label only - use `trigger.labelsAdded` to see all of them.

  **Not supported on Azure DevOps or GitLab** - these providers deliver label changes as `issue_edited`; use `trigger.labelsAdded` / `trigger.labelsRemoved` instead.

  **Example:** `{{trigger.label}}`
</ParamField>

<ParamField path="trigger.labelAction" type="string">
  The action performed: `"added"` or `"removed"`.

  **Not supported on Azure DevOps or GitLab** - these providers deliver label changes as `issue_edited` (a single event can both add and remove labels), so this field is not set; use `trigger.labelsAdded` / `trigger.labelsRemoved` instead.

  **Example:** `{{trigger.labelAction}}`
</ParamField>

<ParamField path="trigger.labelsAdded" type="array<string>">
  All labels added in this change. Match a specific one with the `contains` operator (e.g. `context.trigger.labelsAdded contains "ready-for-development"`).

  **Example:** `{{trigger.labelsAdded}}`
</ParamField>

<ParamField path="trigger.labelsRemoved" type="array<string>">
  All labels removed in this change. Counterpart to `trigger.labelsAdded`.

  **Not supported on Linear** - Linear's webhook does not include the names of removed labels, so this field is omitted for Linear label removals.

  **Example:** `{{trigger.labelsRemoved}}`
</ParamField>

<Note>
  **Provider support:** `trigger.label` and `trigger.labelAction` are populated only by providers that emit a discrete label event - **GitHub, Jira, Linear, and ClickUp**.

  **Azure DevOps** and **GitLab** deliver label changes as `issue_edited` (and a single ADO/GitLab event can add and remove labels at the same time), so `trigger.label`/`trigger.labelAction` are **not set**. Use `trigger.labelsAdded` / `trigger.labelsRemoved` instead - for example, trigger on **Issue edited** with a condition `context.trigger.labelsAdded contains "<label>"`. On Azure DevOps the label is the work-item **tag**.
</Note>

### Assignee Operations

Available for `issue_assigned`, `issue_unassigned`, `pull_request_assigned`, `pull_request_unassigned` events.

<ParamField path="trigger.assignee" type="string">
  Username of the assignee that was added or removed.

  **Example:** `{{trigger.assignee}}`
</ParamField>

<ParamField path="trigger.assigneeAction" type="string">
  The action performed: `"assigned"` or `"unassigned"`.

  **Example:** `{{trigger.assigneeAction}}`
</ParamField>

### Milestone Operations

<ParamField path="trigger.milestone" type="string">
  The milestone that was added or removed.

  **Example:** `{{trigger.milestone}}`
</ParamField>

<ParamField path="trigger.milestoneAction" type="string">
  The action performed: `"added"` or `"removed"`.

  **Example:** `{{trigger.milestoneAction}}`
</ParamField>

### Comment Operations

Available for `issue_commented`, `pull_request_commented`, `pull_request_review_commented` events.

<ParamField path="trigger.commentId" type="string">
  Comment ID from the git provider.

  **Example:** `{{trigger.commentId}}`
</ParamField>

<ParamField path="trigger.commentAuthor" type="string">
  Username of the comment author.

  **Example:** `{{trigger.commentAuthor}}`
</ParamField>

<ParamField path="trigger.commentBody" type="string">
  Full content of the comment.

  **Example:** `{{trigger.commentBody}}`
</ParamField>

<ParamField path="trigger.commentLocation" type="string">
  Where the comment was made: `"issue"` or `"pull_request"`.

  **Example:** `{{trigger.commentLocation}}`
</ParamField>

<ParamField path="trigger.commentCreatedAt" type="string">
  ISO timestamp when the comment was created.

  **Example:** `{{trigger.commentCreatedAt}}`
</ParamField>

### Review Operations

Available for `pull_request_reviewed` events.

<ParamField path="trigger.reviewer" type="string">
  Username of the reviewer.

  **Example:** `{{trigger.reviewer}}`
</ParamField>

<ParamField path="trigger.reviewState" type="string">
  Review state: `"approved"`, `"changes_requested"`, `"commented"`, or `"dismissed"`.

  **Example:** `{{trigger.reviewState}}`
</ParamField>

<ParamField path="trigger.reviewAction" type="string">
  Review action: `"submitted"`, `"edited"`, or `"dismissed"`.

  **Example:** `{{trigger.reviewAction}}`
</ParamField>

### Mention Operations

Available for `mention` events.

<ParamField path="trigger.mentionedBy" type="string">
  Username of the user who mentioned the bot.

  **Example:** `{{trigger.mentionedBy}}`
</ParamField>

<ParamField path="trigger.mentionLocation" type="string">
  Where the mention occurred (e.g., `"issue"`, `"pull_request"`, `"comment"`).

  **Example:** `{{trigger.mentionLocation}}`
</ParamField>

<ParamField path="trigger.mentionContent" type="string">
  The full message or content containing the mention.

  **Example:** `{{trigger.mentionContent}}`
</ParamField>

### Slash Command Operations

Available for `slash_command` events.

<ParamField path="trigger.slashCommand" type="string">
  The slash command that was used (e.g., `"/review"`).

  **Example:** `{{trigger.slashCommand}}`
</ParamField>

<ParamField path="trigger.slashCommandWithMention" type="boolean">
  Whether the slash command was used with an @mention.

  **Example:** `{{trigger.slashCommandWithMention}}`
</ParamField>

***

## Practical Examples

### Example 1: Accessing Issue Properties

Use issue properties in an agent instruction:

```yaml theme={null}
- id: "analyze-issue"
  action: "agent.run"
  params:
    agentId: "triage-bot"
    instruction: |
      Review issue #{{trigger.issue.number}}: "{{trigger.issue.title}}"
      
      Issue details:
      - Author: @{{trigger.issue.author}}
      - State: {{trigger.issue.state}}
      - Labels: {{trigger.issue.labels}}
      - Created: {{trigger.issue.createdAt}}
      
      {{trigger.issue.body}}
```

### Example 2: Clone PR Branch

Use pull request branch information in git operations:

```yaml theme={null}
- id: "clone-pr-branch"
  action: "git.clone"
  params:
    repoFullName: "{{trigger.repository.fullName}}"
    branch: "{{trigger.pullRequest.headBranch}}"
```

### Example 3: Conditional Logic Based on Event State

Use Handlebars helpers for conditional logic:

```yaml theme={null}
- id: "context-aware-agent"
  action: "agent.run"
  params:
    instruction: |
      {{#if (eq trigger.issue.state "closed")}}
        This issue is already closed. Provide a summary of the resolution.
      {{else}}
        This issue is open. Analyze and provide recommendations.
      {{/if}}
      
      {{#if trigger.issue.labels}}
        Labels present: {{trigger.issue.labels}}
      {{else}}
        No labels assigned yet.
      {{/if}}
```

### Example 4: Working with Arrays

Access array elements and iterate:

```yaml theme={null}
- id: "check-assignees"
  action: "agent.run"
  params:
    instruction: |
      Issue assignees:
      {{#if trigger.issue.assignees}}
        {{#each trigger.issue.assignees}}
          - @{{this}}
        {{/each}}
      {{else}}
        No assignees yet.
      {{/if}}
      
      First label: {{trigger.issue.labels.[0]}}
```

### Example 5: Mention the Original Author

Reference the event author in responses:

```yaml theme={null}
- id: "respond-to-user"
  action: "agent.run"
  params:
    instruction: |
      @{{trigger.issue.author}}, I've analyzed your issue and here are my findings...
```

### Example 6: Use Comment Context

Access comment-specific properties:

```yaml theme={null}
- id: "process-comment"
  action: "agent.run"
  params:
    instruction: |
      Process comment by @{{trigger.commentAuthor}}:
      
      {{trigger.commentBody}}
      
      Respond in the {{trigger.commentLocation}} thread.
```

### Example 7: Conditional Repository Selection

Combine with conditional logic for dynamic behavior:

```yaml theme={null}
- id: "clone-code"
  action: "git.clone"
  params:
    repoFullName: |
      {{#if outputs.identify-repos.[0]}}
        {{outputs.identify-repos.[0].repoFullName}}
      {{else}}
        {{trigger.repository.fullName}}
      {{/if}}
    branch: "{{trigger.repository.defaultBranch}}"
```

### Example 8: Filter by Actor Type

Exclude bot-triggered events:

```yaml theme={null}
# In trigger conditions
trigger:
  eventType: "issue_commented"
  conditions:
    - field: "context.actor.type"
      operator: "not_equals"
      value: "Bot"
```

### Example 9: Run Workflow Only When Commits Are Added to a PR

Use the <code>trigger.commitAdded</code> flag to avoid running expensive jobs on metadata-only changes:

```yaml theme={null}
trigger:
  eventType: "pull_request_edited"
  conditions:
    - field: "context.trigger.commitAdded"
      operator: "equals"
      value: true
```

In this setup, the workflow will execute when a pull request is opened or when new commits are pushed, but it will <em>not</em> run if the PR author only updates the title, description, labels, or other metadata.

***

## Custom Event Properties

Workflows triggered by a [Custom Event](/docs/integrations/custom-events) receive the inbound webhook body and any query-string parameters under `trigger.payload.*`. The four well-known meta fields are also lifted into the standard `trigger.*` slots so they look like any other trigger in the runs list.

### Event Metadata

<ParamField path="trigger.eventType" type="string">
  Always `"custom_event"` for Custom Event triggers.
</ParamField>

<ParamField path="trigger.triggerObjectName" type="string">
  Populated from the caller's `objectName` payload field. Falls back to the event's slug (for example, `deployment_completed`) when absent.

  **Example:** `{{trigger.triggerObjectName}}` → `"Deploy #1234 to production"`
</ParamField>

<ParamField path="trigger.triggerObjectNumber" type="string">
  Populated from the caller's `objectNumber` payload field. Empty when absent.

  **Example:** `{{trigger.triggerObjectNumber}}` → `"1234"`
</ParamField>

<ParamField path="trigger.triggerObjectUrl" type="string">
  Populated from the caller's `objectUrl` payload field. Used as the run's click-through link when present.

  **Example:** `{{trigger.triggerObjectUrl}}` → `"https://github.com/acme/api/actions/runs/1234"`
</ParamField>

<ParamField path="trigger.actor.login" type="string">
  Populated from the caller's `actor` payload field. `trigger.actor.type` is always `"Bot"` for Custom Events.

  **Example:** `{{trigger.actor.login}}` → `"deploy-bot"`
</ParamField>

### Payload

<ParamField path="trigger.payload" type="object">
  The full request body. Query-string parameters (other than the reserved `projectId` and `lockKey`) are merged in as top-level string fields. Body values win on conflict.

  **Example:** `{{trigger.payload.environment}}` → `"production"`
</ParamField>

Use dot notation for nested keys: `{{trigger.payload.service.region}}`. Missing intermediate keys evaluate to undefined without throwing.

### Custom Event Identifiers

<ParamField path="trigger.customEvent.id" type="string">
  Internal ID of the Custom Event definition.
</ParamField>

<ParamField path="trigger.customEvent.name" type="string">
  The event's slug, e.g. `"deployment_completed"`. This is what trigger conditions match against.
</ParamField>

<ParamField path="trigger.projectId" type="string | undefined">
  Set when the caller targeted a specific project via `?projectId=`. Undefined on workspace-wide fan-out.
</ParamField>

<ParamField path="trigger.lockKey" type="string | undefined">
  Set when the caller passed `?lockKey=`. Undefined otherwise.
</ParamField>

***

## Template Helpers

Overcut supports Handlebars helpers for advanced logic:

### Comparison Helpers

* `{{#if (eq value1 value2)}}` - Equals
* `{{#if (ne value1 value2)}}` - Not equals
* `{{#if (gt value1 value2)}}` - Greater than
* `{{#if (lt value1 value2)}}` - Less than
* `{{#if (gte value1 value2)}}` - Greater than or equal
* `{{#if (lte value1 value2)}}` - Less than or equal

### Logical Helpers

* `{{#if (and condition1 condition2)}}` - Logical AND
* `{{#if (or condition1 condition2)}}` - Logical OR
* `{{#if (not condition)}}` - Logical NOT

### Iteration

* `{{#each array}}...{{/each}}` - Iterate over arrays
* `{{@index}}` - Current iteration index
* `{{@first}}` / `{{@last}}` - First/last iteration flags

***

## Notes and Best Practices

### Platform Normalization

All properties are automatically normalized from platform-specific formats. For example, GitHub's `pull_request` becomes `pullRequest`, and Jira's `key` becomes `number`.

### Property Availability

Not all properties are available for all events. For example, `trigger.pullRequest` is only available for pull request events, and `trigger.issue` only for issue events. Optional properties may be `null` or `undefined` if not provided by the platform.

### Provider-Specific Properties

While Overcut normalizes events across all platforms, some properties are only available from specific providers due to webhook payload limitations:

**Issue Properties:**

* `confidential` - GitLab only

**Pull Request Properties:**

* `additions`, `deletions`, `changedFiles` - GitHub only
* `autoMerge`, `rebaseable` - GitHub only
* `mergeable` - GitHub and GitLab only
* `requestedReviewers` - GitHub only (GitLab returns empty array)
* `baseSha` - Not available on GitLab

**CI Workflow Properties:**

* `jobCount` - GitLab only
* `queuedAt` - Not available on Azure DevOps
* `trigger.pullRequest.title` in CI events - Bitbucket only

### Array Access

When accessing array elements, always check if the array exists first using `{{#if trigger.issue.labels}}` to avoid template rendering errors.

### Dynamic Workflows

Combine event context with step outputs (`{{outputs.step-id.property}}`) for powerful dynamic workflows that adapt based on runtime data.

***

## Related Documentation

<CardGroup cols={2}>
  <Card title="Triggers" icon="bolt" href="/docs/workflows/triggers">
    Learn about trigger types and event normalization
  </Card>

  <Card title="Workflows" icon="arrow-progress" href="/docs/workflows/workflows">
    Understand workflow structure and template variables
  </Card>

  <Card title="Agent Run" icon="robot" href="/docs/workflows/agent-run">
    Use event context in agent instructions
  </Card>

  <Card title="Git Clone" icon="code-branch" href="/docs/workflows/git-clone">
    Clone repositories using trigger context
  </Card>
</CardGroup>
