راه‌اندازی برنامه و مرجع API

برنامهٔ agent را ثبت کنید، با OAuth نصب کنید، وب‌هوک‌ها را بررسی کنید و از APIهای Pulse استفاده کنید.

این صفحه قرارداد دقیق راه‌اندازی برنامهٔ agent در Pulse را دارد: ثبت، نصب OAuth، وب‌هوک‌ها و درخواست‌های API با هویت برنامه. اگر تازه با این قابلیت آشنا شده‌اید، نخست راهنمای شروع را بخوانید.

مرور

یک برنامه دو هویت دارد: فضای کاری توسعه‌دهنده مالک ثبت و secretهاست، اما هر نصب کاربر برنامه و توکن‌های خودش را دارد. در نسخهٔ اول برنامه فقط در فضای کاری توسعه‌دهندهٔ خودش نصب می‌شود.

ساخت و اجرای آن به این ترتیب است:

  1. برنامه را از یک manifest ثبت کنید و secretهایش را کپی کنید.
  2. یک endpoint نصب راه بیندازید که جریان OAuth را با actor=app اجرا کند.
  3. یک endpoint وب‌هوک راه بیندازید که هر تحویل را بررسی کند و ظرف ۵ ثانیه پاسخ دهد.
  4. به نشست‌ها از طریق Agent Session API پاسخ دهید.
  5. برای بقیهٔ کارها، REST API یا MCP server مربوط به Pulse را با توکن برنامه صدا بزنید.

Secretها را روی سرور خودتان نگه دارید. endpoint نصب باید state در OAuth را بررسی کند و بهتر است پیش از شروع consent یک install secret بخواهد. همهٔ URLهای API این صفحه زیر https://api.trypulse.tech/api/v1 هستند.

ساخت برنامه

هر عضو فضای کاری می‌تواند در Settings → API → Agent apps، کنار OAuth applications، برنامه ثبت کند. نامی قابل‌شناسایی، نام توسعه‌دهنده، URL بازگشت OAuth و URL وب‌هوک را وارد کنید. می‌توانید فرم را پر کنید یا با Import manifest یک manifest از JSON بچسبانید. Pulse secretهای client و webhook را فقط یک‌بار برمی‌گرداند؛ پیش از ترک صفحه آن‌ها را نگه دارید.

ثبت با API

اگر راه‌اندازی را خودکار می‌کنید، همان manifest را با نشست یک فرد واردشده بفرستید. توکن برنامه نمی‌تواند ثبت برنامه‌ها را بسازد یا تغییر دهد.

POST https://api.trypulse.tech/api/v1/agent-apps
Authorization: Bearer $PULSE_SESSION_TOKEN
X-Workspace-ID: $WORKSPACE_ID
Content-Type: application/json

بدنه همان manifest است. پاسخ 201 برنامه و credentialهایش را برمی‌گرداند:

{
  "app": {
    "id": "6ab5a1c04f48187cbd3ce901",
    "client_id": "pulse_app_6ab5a1c04f48",
    "developer_workspace_id": "6a34cfb024a3b4ed28806e3b",
    "owner_user_id": "68cab92a5020377746176588",
    "name": "Scout",
    "description": null,
    "icon_url": null,
    "developer": { "name": "Acme Labs", "url": null },
    "distribution": "private",
    "redirect_uris": ["https://scout.acme.example/oauth/callback"],
    "requested_scopes": ["read", "write", "app:assignable"],
    "webhook": { "enabled": true, "url": "https://scout.acme.example/pulse/webhook", "resource_types": [] },
    "created_at": "2026-09-25T09:00:00.000Z",
    "updated_at": "2026-09-25T09:00:00.000Z"
  },
  "client_id": "pulse_app_6ab5a1c04f48",
  "client_secret": "pulse_sk_2hQpM4c1Yt9sV0eXkR7bNw",
  "webhook_secret": "pwhsec_9fK2mQ7xL0vB3nT8",
  "install_url": "https://api.trypulse.tech/api/v1/oauth/authorize?actor=app&client_id=pulse_app_6ab5a1c04f48&response_type=code&scope=read,write,app:assignable&redirect_uri={redirect_uri}&state={state}&code_challenge={code_challenge}&code_challenge_method=S256"
}

client_secret (pulse_sk_…) و webhook_secret (pwhsec_…) فقط یک‌بار نشان داده می‌شوند. آن‌ها را در یک secrets manager نگه دارید. اگر یکی را از دست دادید، آن را بچرخانید: POST /api/v1/agent-apps/{app_id}/secret یا POST /api/v1/agent-apps/{app_id}/webhook-secret. مقدار قدیمی فوراً از کار می‌افتد.

مالکان و ادمین‌های فضای کاری توسعه‌دهنده می‌توانند برنامه را با PUT /api/v1/agent-apps/{app_id} (کل manifest) تغییر دهند یا با DELETE /api/v1/agent-apps/{app_id} حذف کنند، که اول آن را از همه‌جا حذف نصب می‌کند. GET /api/v1/agent-apps برنامه‌های فضای کاری را فهرست می‌کند. این مسیرها نشست یک شخص را لازم دارند: توکن OAuth یا توکن برنامه 403 SESSION_ONLY_ROUTE می‌گیرد.

مرجع manifest

manifest یک JSON است که با https://api.trypulse.tech/.well-known/agent-app-manifest.schema.json اعتبارسنجی می‌شود. کلیدهای ناشناخته رد می‌شوند، و manifest نامعتبر با 422 VALIDATION_ERROR پاسخ می‌گیرد که برای هر فیلد یک پیام در details دارد.

فیلدالزامیقواعد
$schemaخیرURL همان schema بالا
schemaVersionبله"1.0.0"
nameبله۲ تا ۸۰ نویسه؛ نباید شامل «Pulse» باشد. نام کاربر برنامه می‌شود.
descriptionخیرتا ۱۰۰۰ نویسه
icon_urlخیرURL https:// یک آیکون مربعی؛ Pulse آن را proxy می‌کند
developer.nameبله۲ تا ۸۰ نویسه
developer.urlخیروب‌سایت شما
distributionخیرفقط "private" (پیش‌فرض). "public" در v1 رد می‌شود.
oauth.redirect_urisبله۱ تا ۳۲ URL یکتای https://
oauth.scopesبلهاز میان read، write، issues:create، comments:create، app:assignable، app:mentionable. هرگز admin.
webhook.urlهمراه با webhookURL عمومی https:// روی پورت ۴۴۳ یا ۸۴۴۳
webhook.enabledخیرپیش‌فرض true. تا وقتی false است، هیچ چیزی تحویل نمی‌شود و نمی‌توان کار را به برنامه سپرد یا آن را منشن کرد.
webhook.resource_typesخیررویدادهای داده‌ای اختیاری: Issue، Comment، Project. پیش‌فرض [].

AgentSessionEvent، PermissionChange و OAuthApp همیشه تحویل می‌شوند؛ آوردن آن‌ها در resource_types رد می‌شود.

manifest حداقلی:

{
  "schemaVersion": "1.0.0",
  "name": "Scout",
  "developer": { "name": "Acme Labs" },
  "oauth": {
    "redirect_uris": ["https://scout.acme.example/oauth/callback"],
    "scopes": ["read", "write", "app:assignable"]
  },
  "webhook": { "url": "https://scout.acme.example/pulse/webhook" }
}

manifest کامل:

{
  "$schema": "https://api.trypulse.tech/.well-known/agent-app-manifest.schema.json",
  "schemaVersion": "1.0.0",
  "name": "Scout",
  "description": "Reads a delegated issue, plans the work and reports back in the session.",
  "icon_url": "https://scout.acme.example/icon.png",
  "developer": { "name": "Acme Labs", "url": "https://acme.example" },
  "distribution": "private",
  "oauth": {
    "redirect_uris": [
      "https://scout.acme.example/oauth/callback",
      "https://scout-staging.acme.example/oauth/callback"
    ],
    "scopes": ["read", "write", "app:assignable", "app:mentionable"]
  },
  "webhook": {
    "enabled": true,
    "url": "https://scout.acme.example/pulse/webhook",
    "resource_types": ["Issue", "Comment"]
  }
}

نصب با OAuth

مالک یا ادمین فضای کاری برنامه را از طریق جریان authorization code با actor=app نصب می‌کند. نصب به‌عنوان خود برنامه عمل می‌کند، نه به‌عنوان ادمینی که آن را تأیید کرده است.

۱. ادمین را به URL مجوزدهی بفرستید

GET https://api.trypulse.tech/api/v1/oauth/authorize
  ?client_id=pulse_app_6ab5a1c04f48
  &redirect_uri=https://scout.acme.example/oauth/callback
  &response_type=code
  &scope=read,write,app:assignable,app:mentionable
  &state=8c1f2e0b7d
  &actor=app
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256
پارامترمقدار
client_idclient id برنامهٔ شما
redirect_uriدقیقاً یکی از oauth.redirect_uris در manifest
response_typecode
scopescopeها، جداشده با ویرگول یا فاصله
stateمقداری تصادفی که در callback بررسی‌اش می‌کنید
actorapp
code_challengeSHA-256 از code verifier شما به‌صورت Base64url
code_challenge_methodS256

PKCE الزامی است: درخواستی که code_challenge نداشته باشد، یا از روش دیگری استفاده کند، با invalid_request رد می‌شود. ردهای دیگر با error=unsupported_actor (کلاینت برنامهٔ agent نیست) یا error=invalid_scope (admin درخواست شده، یا یک scope از نوع app:* بدون actor=app) به مسیر بازگشت ریدایرکت می‌شوند.

۲. ادمین تأیید می‌کند

صفحهٔ رضایت، برنامه، توسعه‌دهنده و scopeهایش را نشان می‌دهد، به‌همراه یک انتخابگر تیم: All teams یا Selected teams. فقط مالکان و ادمین‌های فضای کاری برنامه می‌توانند تأیید کنند؛ بقیه پیام رد می‌بینند و چیزی نصب نمی‌شود. تأیید، نصب و کاربر برنامه را می‌سازد و سپس با code و state به redirect_uri شما ریدایرکت می‌کند.

۳. مبادلهٔ code

endpoint توکن form-encoded است. با HTTP Basic (client_secret_basic) احراز هویت کنید، یا client_id و client_secret را در بدنهٔ فرم بفرستید (client_secret_post):

curl -X POST https://api.trypulse.tech/api/v1/oauth/token \
  -u "$PULSE_CLIENT_ID:$PULSE_CLIENT_SECRET" \
  -d grant_type=authorization_code \
  -d code="$CODE" \
  -d redirect_uri=https://scout.acme.example/oauth/callback \
  -d code_verifier="$CODE_VERIFIER"
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "prt_4f1c...",
  "scope": "read write app:assignable app:mentionable",
  "actor": "app",
  "installation_id": "6ab5a2d134765b14d76a6b10",
  "app_user_id": "6ab5a2d134765b14d76a6b12",
  "workspace_id": "6a34cfb024a3b4ed28806e3b"
}

access token یک ساعت اعتبار دارد. آن را با grant_type=refresh_token تازه کنید؛ هر تازه‌سازی یک refresh_token جدید برمی‌گرداند و قبلی از کار می‌افتد، پس همیشه آخرین را ذخیره کنید. refresh token را با POST /api/v1/oauth/revoke باطل کنید و client را با HTTP Basic یا client_id در فرم معرفی کنید: این کار آن grant را تمام می‌کند، پس دیگر هیچ تازه‌سازی کار نمی‌کند و برای گرفتن توکن باید برنامه دوباره نصب شود. access tokenی که قبلاً صادر شده تا زمان انقضا کار می‌کند.

۴. ذخیرهٔ توکن برای هر نصب

کلید مخزن توکن را installation_id بگذارید و workspace_id را کنارش نگه دارید. در هر فراخوانی API، X-Workspace-ID: <workspace_id> را بفرستید. وب‌هوک‌ها همان installation_id را دارند، پس هر رویداد توکن خودش را پیدا می‌کند.

از endpoint نصب خود محافظت کنید. برای هر نصب یک state بسازید و callbackی را که state آن را شما صادر نکرده‌اید رد کنید، و endpoint شروع جریان را پشت یک install secret از خودتان بگذارید تا غریبه‌ها نتوانند نصب برنامهٔ شما را شروع کنند.

شناخت هویت خودتان

GET /api/v1/auth/me برای هر توکن معتبر برنامه پاسخ می‌دهد و scope لازم ندارد. شناسه و نام کاربر خودتان را از همین‌جا بخوانید (نام ممکن است پسوندی مثل Scout 1 داشته باشد):

{
  "user": {
    "id": "6ab5a2d134765b14d76a6b12",
    "display_name": "Scout",
    "user_kind": "application",
    "agent_kind": "app"
  },
  "app": { "id": "6ab5a1c04f48187cbd3ce901", "name": "Scout" },
  "installation_id": "6ab5a2d134765b14d76a6b10"
}

GET /api/v1/workspaces/me فضای کاری نصب را برمی‌گرداند، و GET /api/v1/teams/select تیم‌هایی را که نصب پوشش می‌دهد.

وب‌هوک‌ها

Pulse یک JSON امضاشده را به webhook.url در manifest شما POST می‌کند.

رویداد (type)actionچه زمانی
AgentSessionEventcreated، promptedنشستی برای برنامهٔ شما باز شد؛ یک شخص در آن نوشت یا Stop را زد. ببینید توسعهٔ تعامل agent.
PermissionChangeteamAccessChangedیک ادمین تیم‌هایی را که برنامهٔ شما پوشش می‌دهد تغییر داد
OAuthApprevokedبرنامهٔ شما حذف نصب شد
Issue، Comment، Projectcreate، update، removeاختیاری از طریق resource_types، فقط برای تیم‌های نصب شما. همان دادهٔ وب‌هوک‌های فضای کاری.
Pingcreateفقط از POST /api/v1/agent-apps/{app_id}/webhook/test

هدرهای تحویل

هدرتوضیح
Content-Typeapplication/json; charset=utf-8
User-AgentPulse-Webhook/1
Pulse-Deliveryشناسهٔ پایدار این تحویل، در هر retry یکسان
Pulse-Eventtype پاکت، برای مثال AgentSessionEvent
Pulse-SignatureHMAC-SHA256 هگز با حروف کوچک از بدنهٔ خام، با secret وب‌هوک شما. پیشوند sha256= ندارد.
Pulse-Timestampمیلی‌ثانیهٔ Unix این تلاش. امضا نمی‌شود — از webhook_timestamp بدنه استفاده کنید.

پاکت

فیلدتوضیح
actionجدول بالا را ببینید
typeنوع رویداد؛ همان Pulse-Event
actor{id, type, name}: برای AgentSessionEvent شخصی که کار را سپرد، منشن کرد یا prompt فرستاد؛ برای PermissionChange و OAuthApp مقدار type: system
created_atزمان رخداد (UTC). در هر retry یکسان است.
dataبدنهٔ رویداد. همیشه event_id دارد که در retryها پایدار است.
urlIssue، Comment یا نشست در برنامهٔ Pulse
workspace_idفضای کاری‌ای که برنامهٔ شما در آن نصب شده
webhook_idوب‌هوک برنامهٔ شما
webhook_timestampمیلی‌ثانیهٔ Unix این تلاش. امضا آن را پوشش می‌دهد.
installation_idنصب. توکن را با آن پیدا کنید.
app_user_idشناسهٔ کاربر برنامهٔ شما در این فضای کاری

بررسی هر تحویل

  1. بایت‌های خام بدنه را قبل از اجرای هر JSON parser بخوانید.
  2. HMAC-SHA256 هگز با حروف کوچک همان بایت‌ها را با secret وب‌هوک (از جمله pwhsec_) حساب کنید و به‌صورت constant-time با Pulse-Signature مقایسه کنید.
  3. بدنه را پارس کنید و اگر webhook_timestamp بیش از ۶۰ ثانیه با ساعت شما فاصله دارد ردش کنید. برای این کار از Pulse-Timestamp استفاده نکنید: امضا نمی‌شود.
  4. تکراری‌ها را با data.event_id کنار بگذارید.
import crypto from "node:crypto";

export function verifyPulseWebhook(rawBody: Buffer, signature: string | undefined, secret: string) {
  if (typeof signature !== "string") return null;
  const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(signature, "utf8");
  const b = Buffer.from(expected, "utf8");
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return null;

  const payload = JSON.parse(rawBody.toString("utf8"));
  if (Math.abs(Date.now() - payload.webhook_timestamp) > 60_000) return null;
  return payload;
}

پاسخ ظرف ۵ ثانیه

ظرف ۵ ثانیه هر 2xx را برگردانید، سپس کار را به‌صورت ناهمگام انجام دهید. Pulse ریدایرکت را دنبال نمی‌کند. timeout، خطای شبکه یا وضعیت غیر 2xx یک تلاش ناموفق است که بعد از ۱ دقیقه، ۱ ساعت و ۶ ساعت دوباره انجام می‌شود. وب‌هوکی که در ۲۴ ساعت هیچ تحویل موفقی نداشته باشد و حداقل سه شکست داشته باشد غیرفعال می‌شود؛ گیرنده را درست کنید، یک تست بفرستید و دوباره فعالش کنید.

GET /api/v1/agent-apps/{app_id}/deliveries تحویل‌های اخیر را با تلاش‌هایشان فهرست می‌کند، و POST /api/v1/agent-apps/{app_id}/webhook/test یک Ping امضاشده می‌فرستد.

رویدادهای دسترسی و حذف نصب

PermissionChange / teamAccessChanged:

{
  "action": "teamAccessChanged",
  "type": "PermissionChange",
  "actor": { "id": "", "type": "system", "name": "" },
  "created_at": "2026-09-25T10:00:00.000Z",
  "data": {
    "event_id": "pc_6ab5a2d134765b14d76a6b10_3",
    "installation_id": "6ab5a2d134765b14d76a6b10",
    "all_teams": false,
    "team_ids": ["691897efbdac2591ea059cc4"],
    "added_team_ids": [],
    "removed_team_ids": ["68da1fb8af973c6419b9b3f7"]
  },
  "url": "",
  "workspace_id": "6a34cfb024a3b4ed28806e3b",
  "webhook_id": "6ab5a1c04f48187cbd3ce903",
  "webhook_timestamp": 1790330400000,
  "installation_id": "6ab5a2d134765b14d76a6b10",
  "app_user_id": "6ab5a2d134765b14d76a6b12"
}

OAuthApp / revoked — توکن‌های این نصب را دور بریزید:

{
  "action": "revoked",
  "type": "OAuthApp",
  "actor": { "id": "", "type": "system", "name": "" },
  "created_at": "2026-09-25T11:00:00.000Z",
  "data": {
    "event_id": "rv_6ab5a2d134765b14d76a6b10",
    "installation_id": "6ab5a2d134765b14d76a6b10",
    "app_id": "6ab5a1c04f48187cbd3ce901"
  },
  "url": "",
  "workspace_id": "6a34cfb024a3b4ed28806e3b",
  "webhook_id": "6ab5a1c04f48187cbd3ce903",
  "webhook_timestamp": 1790334000000,
  "installation_id": "6ab5a2d134765b14d76a6b10",
  "app_user_id": "6ab5a2d134765b14d76a6b12"
}

فراخوانی Pulse به‌عنوان برنامه

access token را به‌عنوان bearer token، همراه با X-Workspace-ID، روی REST API مربوط به Pulse و روی MCP server مربوط به Pulse در https://mcp.trypulse.tech/mcp به کار ببرید. هر کاری که انجام می‌دهید به نام کاربر برنامهٔ شما ثبت می‌شود. برای مثال، وقتی کار را شروع می‌کنید Issue سپرده‌شده را به in_progress ببرید:

PUT https://api.trypulse.tech/api/v1/issues/6ab5b0024f48187cbd3ce990
Authorization: Bearer $APP_ACCESS_TOKEN
X-Workspace-ID: 6a34cfb024a3b4ed28806e3b
Content-Type: application/json

{ "status": "in_progress" }

خطاها یک شکل دارند، {code, message, details}:

{
  "code": "APP_STATUS_FORBIDDEN",
  "message": "Agent apps cannot move an issue to done",
  "details": { "status": "done", "allowed": ["in_progress", "qa"] }
}
وضعیتcodeمعنا
401INSTALLATION_REVOKEDبرنامه حذف نصب شده است. توکن‌ها را دور بریزید.
403INSUFFICIENT_SCOPEتوکن یک scope را ندارد؛ details.required نام آن را می‌آورد. به‌صورت WWW-Authenticate: Bearer error="insufficient_scope" هم فرستاده می‌شود. برنامه را با آن scope دوباره نصب کنید.
403APP_STATUS_FORBIDDENبرنامه‌ها Issue را فقط در backlog، todo، in_progress یا qa می‌سازند، و فقط به in_progress یا qa جابه‌جا می‌کنند
403SESSION_ONLY_ROUTEاین مسیر نشست یک شخص را لازم دارد (رضایت، مدیریت برنامه و وب‌هوک، رمزهای عبور)
400INVALID_DELEGATEهمراه با details.reason: app_actor: برنامه‌ها نمی‌توانند delegate را تنظیم، تغییر یا پاک کنند

Agent Session API برای هر نشست ۱۰ فعالیت در ثانیه و برای هر نصب ۶۰۰ درخواست در دقیقه را می‌پذیرد؛ بیش از آن با 429 RATE_LIMIT_EXCEEDED و Retry-After پاسخ می‌دهد.

مرجع مدل agent در Pulse

سه نوع agent

نوعagent_kindچه کسی آن را می‌سازدکجا اجرا می‌شود
Pulse Agentdeploymentداخلیدرون Pulse
agent شخصیpersonalهر عضو، برای خودشدرون Pulse، با دستورالعمل‌های خود عضو
برنامهٔ agentappیک توسعه‌دهنده؛ ادمین فضای کاری نصبش می‌کندروی سرور توسعه‌دهنده

هر سه کاربر application هستند (user_kind: application) و یک picker مشترک دارند. agent_kind آن‌ها را روی آبجکت‌های کاربر، delegate در Issue، نتایج /users/select و GET /api/v1/agents از هم جدا می‌کند (این مسیر برنامه‌های نصب‌شده را فقط با ?include_apps=true و Pulse Agent را فقط با ?include_deployment=true برمی‌گرداند):

{
  "id": "6ab5a2d134765b14d76a6b12",
  "display_name": "Scout",
  "user_kind": "application",
  "agent_kind": "app"
}

Delegate و assignee

تفویض Issue به یک agent، delegate آن را تنظیم می‌کند، نه assignee را. یک assignee انسانی همیشه مسئول کار می‌ماند:

  • اگر Issue assignee ندارد، کسی که تفویض می‌کند در همان write به assignee تبدیل می‌شود.
  • کسی که بیرون از تیم Issue است نمی‌تواند Issue بدون assignee را تفویض کند: write با DELEGATION_REQUIRES_ASSIGNEE شکست می‌خورد و باید یک هم‌تیمی را به‌عنوان assignee تعیین کند.
  • حذف delegate، یا تفویض به agent دیگر، session برنامه را با end_reason: undelegated پایان می‌دهد.

برای اینکه افراد چطور این کار را انجام می‌دهند، تخصیص و تفویض Issueها را ببینید.

Issue فقط وقتی قابل تفویض به یک برنامهٔ agent است که همهٔ این شرط‌ها برقرار باشد. در غیر این صورت picker برنامه را غیرقابل‌دسترس با unavailable_reason منطبق نشان می‌دهد:

شرطunavailable_reason وقتی برقرار نیست
نصب فعالی که تیم Issue را پوشش دهدapp_not_installed_for_team
scope‏ app:assignableapp_missing_scope
وب‌هوک برنامه فعال باشدapp_webhook_disabled

مرجع scopeها

برنامهٔ agent scopeها را در manifest خود و هنگام نصب درخواست می‌کند. Pulse آن‌ها را روی هر درخواستی که با token برنامه زده شود اعمال می‌کند.

Scopeچه چیزی می‌دهد
readخواندن آنچه تیم‌های برنامه می‌توانند بخوانند. grant بدون scope همان read است.
writeساخت، تغییر و حذف. issues:create و comments:create را هم شامل می‌شود.
issues:createفقط ساخت Issue (POST /api/v1/issues).
comments:createفقط ساخت Comment و پاسخ (POST /api/v1/comments).
app:assignableافراد می‌توانند Issue را به برنامه تفویض کنند.
app:mentionableافراد می‌توانند برنامه را در Commentها @منشن کنند.

admin هرگز به برنامهٔ agent داده نمی‌شود. بیشتر برنامه‌ها read,write,app:assignable,app:mentionable را درخواست می‌کنند. درخواستی که scope لازم مسیر را ندارد با 403 INSUFFICIENT_SCOPE رد می‌شود که scope را در details.required نام می‌برد. GET /api/v1/auth/me،‏ GET /api/v1/workspaces/me و GET /api/v1/teams/select به هیچ scopeای نیاز ندارند.

دسترسی تیم

هنگام نصب، ادمین All teams یا Selected teams را انتخاب می‌کند. کاربر برنامه عضو آن تیم‌ها می‌شود و token آن فقط همان‌جا می‌خواند و می‌نویسد: Issue تیم دیگر 403 برمی‌گرداند و Issue شخصیِ یک نفر هم 403.

ادمین‌ها هر زمان می‌توانند تیم‌ها را عوض کنند یا برنامه را از Installed agents حذف نصب کنند. برنامه فوراً باخبر می‌شود:

تغییروب‌هوکی که برنامه دریافت می‌کندچه اتفاق دیگری می‌افتد
تیم‌ها عوض شدPermissionChange / teamAccessChangedتفویض‌ها روی تیم‌های حذف‌شده آزاد می‌شوند؛ sessionهایشان با end_reason: team_removed پایان می‌یابند
حذف نصبOAuthApp / revokedtoken دیگر کار نمی‌کند (401 INSTALLATION_REVOKED)؛ همهٔ تفویض‌ها آزاد می‌شوند؛ sessionها با end_reason: uninstalled پایان می‌یابند

محموله‌ها در راه‌اندازی برنامه و مرجع API آمده‌اند.

کارهایی که برنامهٔ agent نمی‌تواند انجام دهد

در v1 برنامهٔ agent نمی‌تواند:

  • Issue را ببندد. می‌تواند Issue را در backlog، todo، in_progress یا qa بسازد، و Issue را فقط به in_progress یا qa ببرد. هر status دیگری 403 APP_STATUS_FORBIDDEN برمی‌گرداند. کار را با یک response برگردانید؛ یک نفر آن را می‌بندد.
  • تفویض را تغییر دهد. تنظیم، تغییر یا پاک‌کردن delegate_id پاسخ 400 INVALID_DELEGATE با details.reason: app_actor می‌دهد، حتی برای تفویض خودش.
  • بیرون از تیم‌هایش عمل کند. Issueها، Commentها و sessionهای تیم‌های دیگر در دسترس نیستند.
  • در توضیحات یا اسناد منشن شود. فقط منشن در Comment یک session باز می‌کند.
  • بیرون از فضای کاری خودش نصب شود. برنامه‌ها در v1 خصوصی‌اند.

پرسش‌های متداول

مرجع API agent session

این مرجع endpointها، محموله‌های کامل رویداد و خطاهای لازم برای پیاده‌سازی را نگه می‌دارد.

APIهای session

متدمسیرکار
GET/agent-sessions/{session_id}دریافت یک session
GET/agent-sessionsفهرست sessionهای شما: issue_id، state، cursor، limit (تا ۱۰۰)
GET/agent-sessions/{session_id}/activitiesخواندن گفتگو: after_seq، limit (تا ۲۰۰)
POST/agent-sessions/{session_id}/activitiesفرستادن یک activity
PATCH/agent-sessions/{session_id}به‌روزرسانی plan و URLهای خارجی
POST/agent-sessionsباز کردن session به دست خودتان روی یک Issue یا Comment

همهٔ مسیرها زیر https://api.trypulse.tech/api/v1 هستند.

خواندن گفتگو

گفتگو را از activityها بازسازی کنید، نه از Commentهای Issue. فهرست، پیام‌های افراد را هم همراه با نویسنده‌شان (author.kind: user) دارد. seq همیشه افزایش می‌یابد اما پیوسته نیست، پس با after_seq صفحه‌بندی کنید:

GET https://api.trypulse.tech/api/v1/agent-sessions/sess_01J9Z3K8T5N2/activities?after_seq=4&limit=100
{
  "data": [
    {
      "id": "act_01J9Z4B2Q7",
      "seq": 9,
      "type": "prompt",
      "content": { "type": "prompt", "body": "Also check the Go client, please." },
      "ephemeral": false,
      "superseded_by_seq": null,
      "signal": null,
      "signal_metadata": null,
      "author": { "kind": "user", "id": "68d91d3629c051fe043158f9", "name": "Sara Ahmadi", "avatar_url": null },
      "created_at": "2026-09-25T09:15:40.000Z"
    }
  ],
  "has_more": false,
  "last_seq": 9
}

دوباره با after_seq برابر last_seq درخواست بدهید. GET /agent-sessions در جهت عکس صفحه‌بندی می‌کند: جدیدترین اول، با next_cursor (در صفحهٔ آخر null) که آن را به‌صورت cursor برمی‌گردانید.

Planهای agent

Plan چک‌لیستی است که افراد در سربرگ session می‌بینند. هر بار کل آرایه را بفرستید (حداکثر ۵۰ مورد):

PATCH https://api.trypulse.tech/api/v1/agent-sessions/sess_01J9Z3K8T5N2
Content-Type: application/json

{
  "plan": [
    { "content": "Read the issue and its threads", "status": "completed" },
    { "content": "Draft the change", "status": "inProgress" },
    { "content": "Report back", "status": "pending" }
  ]
}

status یکی از pending، inProgress، completed یا canceled است؛ content تا ۵۰۰ نویسه.

لینک‌های خارجی session

افراد را به UI خودتان برای این session لینک دهید (حداکثر ۱۰ لینک، هر url یکتا و https://، label تا ۶۰ نویسه). فهرست را با external_urls جایگزین کنید، یا با added_external_urls و removed_external_urls تغییرش دهید (نه هر دو با هم):

{ "added_external_urls": [{ "label": "Open in Scout", "url": "https://scout.acme.example/runs/42" }] }
{ "removed_external_urls": ["https://scout.acme.example/runs/42"] }

ست کردن URL خارجی ظرف ۱۰ ثانیه بعد از created پاسخ دادن به حساب می‌آید.

باز کردن session به دست خودتان

POST /agent-sessions با یک issue_id یا comment_id که installation شما پوشش می‌دهد، کاری را شروع می‌کند که کسی تفویض نکرده است:

{ "issue_id": "6ab5b0024f48187cbd3ce990" }

پاسخ، session جدید است (201)، با app user شما به‌عنوان creator. برای آن هیچ وب‌هوک created فرستاده نمی‌شود. روی یک Comment، برای هر برنامه در هر نخ فقط یک session باز وجود دارد: اگر session شما از قبل وجود داشته باشد، با 200 برمی‌گردد.

وقتی Pulse یک session را پایان می‌دهد

برخی پایان‌ها به انتخاب برنامهٔ شما نیستند:

end_reasonعلتچطور پایان می‌یابد
stoppedیک نفر Stop را زدهstopping، سپس prompted با signal: "stop"؛ بعد از activity نهایی شما یا گذشت ۶۰ ثانیه پایان می‌یابد
undelegatedتفویض Issue برداشته شده، یا Issue به agent دیگری تفویض شدهمثل stopped
uninstalledبرنامهٔ شما uninstall شدهفوراً پایان می‌یابد، بدون prompted. رویداد OAuthApp / revoked را دریافت می‌کنید.
team_removedinstallation شما دیگر تیم Issue را پوشش نمی‌دهدفوراً پایان می‌یابد، بدون prompted. رویداد PermissionChange / teamAccessChanged را دریافت می‌کنید.
issue_deletedIssue حذف شدهفوراً پایان می‌یابد، بدون prompted. اگر Issue را انتخاب کرده باشید، رویداد remove آن را دریافت می‌کنید.

برای stopped و undelegated، end_reason به محض ورود session به stopping ست می‌شود، تا بدانید چرا متوقف می‌شوید. وقتی session پایان یافت (ended_at ست شده)، هر write پاسخ 409 می‌گیرد:

{ "code": "SESSION_ENDED", "message": "This session has ended", "details": { "end_reason": "stopped" } }

مرجع محمولهٔ رویدادها

نمونه‌های زیر پاکت کامل وب‌هوک و فیلدهایی را که برنامه می‌گیرد نشان می‌دهند. پیش از استفاده از محموله، هر تحویل را بررسی کنید.

رویداد created

{
  "action": "created",
  "type": "AgentSessionEvent",
  "actor": { "id": "68d91d3629c051fe043158f9", "type": "user", "name": "Sara Ahmadi" },
  "created_at": "2026-09-25T09:12:03.120Z",
  "data": {
    "event_id": "ase_sess_01J9Z3K8T5N2_created",
    "agent_session": {
      "id": "sess_01J9Z3K8T5N2",
      "state": "pending",
      "unresponsive_since": null,
      "issue": {
        "id": "6ab5b0024f48187cbd3ce990",
        "identifier": "PUL-123",
        "title": "Webhook retries ignore Retry-After",
        "url": "https://app.trypulse.tech/pulse/issues/6ab5b0024f48187cbd3ce990",
        "team": { "id": "691897efbdac2591ea059cc4", "key": "PUL", "name": "Pulse" }
      },
      "comment": {
        "id": "6ab5b0414f48187cbd3ce9b2",
        "body": "@Scout can you look at this?",
        "url": "https://app.trypulse.tech/pulse/issues/6ab5b0024f48187cbd3ce990#comment-6ab5b0414f48187cbd3ce9b2"
      },
      "creator": { "id": "68d91d3629c051fe043158f9", "name": "Sara Ahmadi" },
      "app_user_id": "6ab5a2d134765b14d76a6b12",
      "plan": [],
      "external_urls": [],
      "created_at": "2026-09-25T09:12:03.120Z",
      "updated_at": "2026-09-25T09:12:03.120Z",
      "ended_at": null,
      "end_reason": null
    },
    "previous_comments": [
      {
        "id": "6ab5b0304f48187cbd3ce9a8",
        "body": "Seen on staging too.",
        "author": { "id": "68cab92a5020377746176588", "name": "Alireza Attari" },
        "created_at": "2026-09-25T08:50:00.000Z"
      }
    ],
    "guidance": [
      { "origin": "workspace", "body": "Write in English. Link every issue you mention." },
      { "origin": "team", "team_id": "691897efbdac2591ea059cc4", "body": "Never touch the billing module." }
    ],
    "prompt_context": "<issue identifier=\"PUL-123\" url=\"…\">…</issue>…"
  },
  "url": "https://app.trypulse.tech/pulse/issues/6ab5b0024f48187cbd3ce990",
  "workspace_id": "6a34cfb024a3b4ed28806e3b",
  "webhook_id": "6ab5a1c04f48187cbd3ce903",
  "webhook_timestamp": 1790327523120,
  "installation_id": "6ab5a2d134765b14d76a6b10",
  "app_user_id": "6ab5a2d134765b14d76a6b12"
}
  • issue برای منشن روی Comment یک پروژه null است. comment برای تفویض null است.
  • creator کسی است که Issue را به برنامهٔ شما تفویض کرده یا آن را منشن کرده.
  • previous_comments Commentهای قبلی نخ هستند، از قدیمی‌ترین به جدیدترین.
  • guidance ابتدا قاعدهٔ workspace و سپس قاعدهٔ تیم Issue است. در صورت تعارض، قاعدهٔ تیم برنده است.

prompt_context

prompt_context همین context در قالب یک رشتهٔ XML است، آماده برای prompt مدل. از تگ‌های context پالس استفاده می‌کند:

<issue identifier="PUL-123" url="https://app.trypulse.tech/pulse/issues/6ab5b0024f48187cbd3ce990">
  <title>Webhook retries ignore Retry-After</title>
  <description>Deliveries that get a 429 retry on the fixed schedule.</description>
  <team>Pulse</team>
  <label>bug</label>
  <project>Integrations</project>
</issue>
<primary-directive-thread comment-id="6ab5b0414f48187cbd3ce9b2">
  <comment author="Sara Ahmadi" created-at="2026-09-25T09:12:03.120Z">@Scout can you look at this?</comment>
</primary-directive-thread>
<guidance>
  <guidance-rule origin="workspace">Write in English. Link every issue you mention.</guidance-rule>
  <guidance-rule origin="team" team="PUL">Never touch the billing module.</guidance-rule>
</guidance>
<repository-hint repository="pulse/pulse-api"/>
تگمحتوا
<issue identifier url>Issue، با <title>، <description> (Markdown)، <team>، <label> (تکرارشونده)، <project> و <parent-issue> وقتی مقدار داشته باشند
<primary-directive-thread comment-id>نخی که برنامهٔ شما را منشن کرده. تفویض چنین نخی ندارد.
<other-thread comment-id>نخ‌های دیگر Issue
<comment author created-at>یک Comment درون یک نخ
<guidance><guidance-rule origin="workspace">، سپس <guidance-rule origin="team" team="KEY">
<repository-hint repository>repositoryای که تیم Issue کار را به آن می‌سپارد. فقط یک راهنمایی است: دسترسی git را خودتان فراهم کنید.

فقط guidance فضای کاری و تیم فرستاده می‌شود. guidance سراسری پلتفرم و guidance شخصی افراد هرگز فرستاده نمی‌شود. prompt_context حداکثر ۶۴ KB است: ابتدا قدیمی‌ترین بلوک‌های <other-thread> حذف می‌شوند، سپس description کوتاه می‌شود.

رویداد prompted

یک نفر در session نوشته، یا Stop را زده. data هم session و هم پیام را دارد:

{
  "action": "prompted",
  "type": "AgentSessionEvent",
  "actor": { "id": "68d91d3629c051fe043158f9", "type": "user", "name": "Sara Ahmadi" },
  "created_at": "2026-09-25T09:15:40.000Z",
  "data": {
    "event_id": "ase_sess_01J9Z3K8T5N2_act_9",
    "agent_session": { "id": "sess_01J9Z3K8T5N2", "state": "pending" },
    "agent_activity": {
      "id": "act_01J9Z4B2Q7",
      "content": { "type": "prompt", "body": "Also check the Go client, please." },
      "author": { "id": "68d91d3629c051fe043158f9", "name": "Sara Ahmadi" },
      "created_at": "2026-09-25T09:15:40.000Z"
    }
  },
  "url": "https://app.trypulse.tech/pulse/issues/6ab5b0024f48187cbd3ce990",
  "workspace_id": "6a34cfb024a3b4ed28806e3b",
  "webhook_id": "6ab5a1c04f48187cbd3ce903",
  "webhook_timestamp": 1790327740000,
  "installation_id": "6ab5a2d134765b14d76a6b10",
  "app_user_id": "6ab5a2d134765b14d76a6b12"
}

agent_session این‌جا خلاصه شده است؛ در عمل کل session است، مثل created. پیام در agent_activity.content.body است. وقتی agent_activity.signal برابر "stop" باشد، آن فرد Stop را زده است — ببینید سیگنال‌ها.

خطاها

وضعیتcodeمعنا
401UNAUTHORIZEDtoken وجود ندارد، منقضی شده یا باطل شده
403INSUFFICIENT_SCOPEread یا write وجود ندارد؛ details.required را ببینید
404RESOURCE_NOT_FOUNDsession متعلق به برنامهٔ شما نیست، یا Issue یا Commentی است که نمی‌توانید ببینید
409SESSION_ENDEDsession به دست یک نفر یا Pulse پایان یافته
422PROMPT_IS_HUMAN_ONLYیک prompt فرستاده‌اید
422VALIDATION_ERRORبدنه مطابقت ندارد، مثلاً ephemeral روی یک response؛ details را ببینید
429RATE_LIMIT_EXCEEDEDبیش از ۱۰ activity در ثانیه در یک session، یا ۶۰۰ درخواست در دقیقه برای installation. به اندازهٔ Retry-After ثانیه صبر کنید.

آخرین به‌روزرسانی