Sentry
Start AGNT5 workflows automatically from Sentry issues, errors, and comments.
Connect Sentry to AGNT5 and your workflows will start automatically whenever an issue, error, or comment event fires. Every delivery is signature-verified before any workflow runs.
Setup
1. Create the integration in Studio
- Go to Settings → Integrations and click Add Integration.
- Pick Sentry.
- Fill in a name for the integration.
- Choose the environment that should receive triggers.
2. Create an integration in Sentry
-
Go to Settings → Integrations → Custom Integrations and click Create New Integration.
-
Fill in the required details and paste the webhook URL from AGNT5 Studio.
-
Under Permissions, configure access for each resource. For example:
Note:Permission Value Project Read Team Read Release No Access Distribution No Access Issue & Event Read Organization Read Member Read Alerts No Access -
Under Webhooks, check the event types you want to trigger workflows. For example:
Note:issue, error, comment, seer, preprod_artifact
-
Click Save Changes.
-
Copy the Client Secret and paste it into the Signing secret field in Studio.
[screenshot: Sentry Custom Integrations page with the Create New Integration button and the Client Secret field highlighted]
Events
Each Sentry event has a name in the format sentry.<resource>.<action>. Pass this name to event() in your workflow trigger.
| Resource | Action | Full event name |
|---|---|---|
issue | created | sentry.issue.created |
issue | resolved | sentry.issue.resolved |
issue | assigned | sentry.issue.assigned |
issue | ignored | sentry.issue.ignored |
error | created | sentry.error.created |
comment | created | sentry.comment.created |
Workflow examples
Issue events
Workflows receive the webhook envelope as keyword arguments (**envelope). The body field is the raw verified request body. It may arrive as a JSON string or an already-parsed dict, so parse defensively.
import json
from agnt5 import WorkflowContext, workflow
from agnt5.types import event
def _parse_body(envelope: dict) -> dict:
body = envelope.get("body", {})
if isinstance(body, str):
try:
body = json.loads(body)
except json.JSONDecodeError:
return {}
return body if isinstance(body, dict) else {}
@workflow(
name="triage_sentry_issue",
triggers=[event("sentry.issue.created")],
)
async def triage_sentry_issue(ctx: WorkflowContext, **envelope) -> dict:
body = _parse_body(envelope)
issue = body.get("data", {}).get("issue", {})
ctx.logger.info(
"Sentry issue.created: %s (level=%s)"
% (issue.get("title", "unknown"), issue.get("level", "unknown"))
)
# add your triage logic here, e.g. open a ticket, page on-call
return {
"issue_id": issue.get("id"),
"title": issue.get("title"),
"level": issue.get("level"),
"event_type": envelope.get("event_type"),
}Comment events
Comment payloads nest the comment text several levels deep. Extract defensively:
@workflow(
name="log_sentry_comment",
triggers=[event("sentry.comment.created")],
)
async def log_sentry_comment(ctx: WorkflowContext, **envelope) -> dict:
body = _parse_body(envelope)
data = body.get("data", {})
comment = data.get("comment") or body.get("comment") or {}
issue = data.get("issue") or body.get("issue") or {}
actor = body.get("actor") or {}
user = comment.get("user") or comment.get("author") or {}
author = (
comment.get("author_name")
or user.get("name")
or actor.get("name")
or "unknown"
)
text = (
comment.get("text")
or comment.get("message")
or data.get("text")
or ""
)
ctx.logger.info(
"Sentry comment from %s on %s: %s"
% (author, issue.get("short_id", "unknown"), text[:200])
)
return {"author": author, "issue": issue.get("short_id"), "comment": text}Viewing triggered runs in Studio
After a Sentry event fires, the run appears in Studio → Runs within seconds. Open the run to see the envelope inputs and workflow output in the trace.
[screenshot: Studio Runs list showing a completed triage_sentry_issue run, with the run detail open showing the sentry.issue.created event_type and the workflow output]
Envelope structure
Every Sentry-triggered run receives this envelope as **envelope:
{
"_webhook": true,
"source": "sentry",
"integration_id": "int_abc123",
"event_type": "sentry.issue.created",
"idempotency_key": "req_9f3c…",
"timestamp": 1733337600,
"headers": { "sentry-hook-resource": "issue", "request-id": "req_9f3c…" },
"body": "{\"action\":\"created\",\"data\":{\"issue\":{…}}}"
}body is the raw signature-verified request body. Parse it with json.loads before use.
Signature verification
- Every delivery is verified using
sentry-hook-signaturebefore any workflow runs. - Requests with an invalid or missing signature are rejected with
401.
Delivery semantics
- Sentry retries failed deliveries automatically.
- AGNT5 deduplicates using the
Request-IDheader. - A retry replays the original run instead of starting a new one.
Related
- Event sources overview
- Webhooks: trigger mechanism, signature verification, and delivery semantics
- Workflows: how to write and run workflows