راهاندازی برنامه و مرجع API
برنامهٔ agent را ثبت کنید، با OAuth نصب کنید، وبهوکها را بررسی کنید و از APIهای Pulse استفاده کنید.
این صفحه قرارداد دقیق راهاندازی برنامهٔ agent در Pulse را دارد: ثبت، نصب OAuth، وبهوکها و درخواستهای API با هویت برنامه. اگر تازه با این قابلیت آشنا شدهاید، نخست راهنمای شروع را بخوانید.
مرور
یک برنامه دو هویت دارد: فضای کاری توسعهدهنده مالک ثبت و secretهاست، اما هر نصب کاربر برنامه و توکنهای خودش را دارد. در نسخهٔ اول برنامه فقط در فضای کاری توسعهدهندهٔ خودش نصب میشود.
ساخت و اجرای آن به این ترتیب است:
- برنامه را از یک manifest ثبت کنید و secretهایش را کپی کنید.
- یک endpoint نصب راه بیندازید که جریان OAuth را با
actor=appاجرا کند. - یک endpoint وبهوک راه بیندازید که هر تحویل را بررسی کند و ظرف ۵ ثانیه پاسخ دهد.
- به نشستها از طریق Agent Session API پاسخ دهید.
- برای بقیهٔ کارها، 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 | همراه با webhook | URL عمومی 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_id | client id برنامهٔ شما |
redirect_uri | دقیقاً یکی از oauth.redirect_uris در manifest |
response_type | code |
scope | scopeها، جداشده با ویرگول یا فاصله |
state | مقداری تصادفی که در callback بررسیاش میکنید |
actor | app |
code_challenge | SHA-256 از code verifier شما بهصورت Base64url |
code_challenge_method | S256 |
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 | چه زمانی |
|---|---|---|
AgentSessionEvent | created، prompted | نشستی برای برنامهٔ شما باز شد؛ یک شخص در آن نوشت یا Stop را زد. ببینید توسعهٔ تعامل agent. |
PermissionChange | teamAccessChanged | یک ادمین تیمهایی را که برنامهٔ شما پوشش میدهد تغییر داد |
OAuthApp | revoked | برنامهٔ شما حذف نصب شد |
Issue، Comment، Project | create، update، remove | اختیاری از طریق resource_types، فقط برای تیمهای نصب شما. همان دادهٔ وبهوکهای فضای کاری. |
Ping | create | فقط از POST /api/v1/agent-apps/{app_id}/webhook/test |
هدرهای تحویل
| هدر | توضیح |
|---|---|
Content-Type | application/json; charset=utf-8 |
User-Agent | Pulse-Webhook/1 |
Pulse-Delivery | شناسهٔ پایدار این تحویل، در هر retry یکسان |
Pulse-Event | type پاکت، برای مثال AgentSessionEvent |
Pulse-Signature | HMAC-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ها پایدار است. |
url | Issue، Comment یا نشست در برنامهٔ Pulse |
workspace_id | فضای کاریای که برنامهٔ شما در آن نصب شده |
webhook_id | وبهوک برنامهٔ شما |
webhook_timestamp | میلیثانیهٔ Unix این تلاش. امضا آن را پوشش میدهد. |
installation_id | نصب. توکن را با آن پیدا کنید. |
app_user_id | شناسهٔ کاربر برنامهٔ شما در این فضای کاری |
بررسی هر تحویل
- بایتهای خام بدنه را قبل از اجرای هر JSON parser بخوانید.
- HMAC-SHA256 هگز با حروف کوچک همان بایتها را با secret وبهوک (از جمله
pwhsec_) حساب کنید و بهصورت constant-time باPulse-Signatureمقایسه کنید. - بدنه را پارس کنید و اگر
webhook_timestampبیش از ۶۰ ثانیه با ساعت شما فاصله دارد ردش کنید. برای این کار ازPulse-Timestampاستفاده نکنید: امضا نمیشود. - تکراریها را با
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 | معنا |
|---|---|---|
401 | INSTALLATION_REVOKED | برنامه حذف نصب شده است. توکنها را دور بریزید. |
403 | INSUFFICIENT_SCOPE | توکن یک scope را ندارد؛ details.required نام آن را میآورد. بهصورت WWW-Authenticate: Bearer error="insufficient_scope" هم فرستاده میشود. برنامه را با آن scope دوباره نصب کنید. |
403 | APP_STATUS_FORBIDDEN | برنامهها Issue را فقط در backlog، todo، in_progress یا qa میسازند، و فقط به in_progress یا qa جابهجا میکنند |
403 | SESSION_ONLY_ROUTE | این مسیر نشست یک شخص را لازم دارد (رضایت، مدیریت برنامه و وبهوک، رمزهای عبور) |
400 | INVALID_DELEGATE | همراه با details.reason: app_actor: برنامهها نمیتوانند delegate را تنظیم، تغییر یا پاک کنند |
Agent Session API برای هر نشست ۱۰ فعالیت در ثانیه و برای هر نصب ۶۰۰ درخواست در دقیقه را میپذیرد؛ بیش از آن با 429 RATE_LIMIT_EXCEEDED و Retry-After پاسخ میدهد.
مرجع مدل agent در Pulse
سه نوع agent
| نوع | agent_kind | چه کسی آن را میسازد | کجا اجرا میشود |
|---|---|---|---|
| Pulse Agent | deployment | داخلی | درون Pulse |
| agent شخصی | personal | هر عضو، برای خودش | درون Pulse، با دستورالعملهای خود عضو |
| برنامهٔ agent | app | یک توسعهدهنده؛ ادمین فضای کاری نصبش میکند | روی سرور توسعهدهنده |
هر سه کاربر 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:assignable | app_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 / revoked | token دیگر کار نمیکند (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_removed | installation شما دیگر تیم Issue را پوشش نمیدهد | فوراً پایان مییابد، بدون prompted. رویداد PermissionChange / teamAccessChanged را دریافت میکنید. |
issue_deleted | Issue حذف شده | فوراً پایان مییابد، بدون 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_commentsCommentهای قبلی نخ هستند، از قدیمیترین به جدیدترین.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 | معنا |
|---|---|---|
401 | UNAUTHORIZED | token وجود ندارد، منقضی شده یا باطل شده |
403 | INSUFFICIENT_SCOPE | read یا write وجود ندارد؛ details.required را ببینید |
404 | RESOURCE_NOT_FOUND | session متعلق به برنامهٔ شما نیست، یا Issue یا Commentی است که نمیتوانید ببینید |
409 | SESSION_ENDED | session به دست یک نفر یا Pulse پایان یافته |
422 | PROMPT_IS_HUMAN_ONLY | یک prompt فرستادهاید |
422 | VALIDATION_ERROR | بدنه مطابقت ندارد، مثلاً ephemeral روی یک response؛ details را ببینید |
429 | RATE_LIMIT_EXCEEDED | بیش از ۱۰ activity در ثانیه در یک session، یا ۶۰۰ درخواست در دقیقه برای installation. به اندازهٔ Retry-After ثانیه صبر کنید. |
آخرین بهروزرسانی