@@ -29,22 +29,26 @@ Send a `thought` activity within the first few seconds of receiving a webhook:
2929<Tab title = " TypeScript" >
3030
3131``` typescript
32- async function handleWebhook(webhook : AgentRunActivityWebhook ) {
32+ import { PlaneClient } from ' @makeplane/plane-node-sdk' ;
33+
34+ async function handleWebhook(webhook : AgentRunActivityWebhook , credentials : { bot_token: string ; workspace_slug: string }) {
35+ const planeClient = new PlaneClient ({
36+ baseUrl: process .env .PLANE_API_URL || ' https://api.plane.so' ,
37+ accessToken: credentials .bot_token ,
38+ });
39+
3340 const agentRunId = webhook .agent_run .id ;
34-
41+
3542 // IMMEDIATELY acknowledge receipt
36- await planeClient .agentRuns .activities .create (workspaceSlug , agentRunId , {
37- type: " thought" ,
38- content: {
39- type: " thought" ,
40- body: " Received your request. Analyzing..." ,
41- },
43+ await planeClient .agentRuns .activities .create (credentials .workspace_slug , agentRunId , {
44+ type: ' thought' ,
45+ content: { type: ' thought' , body: ' Received your request. Analyzing...' },
4246 });
4347
4448 // Now proceed with actual processing
4549 // This can take longer since user knows agent is working
4650 const result = await processRequest (webhook );
47-
51+
4852 // ... rest of the logic
4953}
5054```
@@ -53,23 +57,30 @@ async function handleWebhook(webhook: AgentRunActivityWebhook) {
5357<Tab title = " Python" >
5458
5559``` python
56- async def handle_webhook (webhook : dict ):
60+ from plane import PlaneClient
61+ from plane.models.agent_runs import CreateAgentRunActivity
62+
63+ def handle_webhook (webhook : dict , credentials : dict ):
64+ plane_client = PlaneClient(
65+ base_url = os.getenv(" PLANE_API_URL" , " https://api.plane.so" ),
66+ access_token = credentials[" bot_token" ],
67+ )
68+
5769 agent_run_id = webhook[" agent_run" ][" id" ]
58-
70+
5971 # IMMEDIATELY acknowledge receipt
6072 plane_client.agent_runs.activities.create(
61- workspace_slug = workspace_slug,
62- agent_run_id = agent_run_id,
63- type = " thought" ,
64- content = {
65- " type" : " thought" ,
66- " body" : " Received your request. Analyzing..." ,
67- },
73+ workspace_slug = credentials[" workspace_slug" ],
74+ run_id = agent_run_id,
75+ data = CreateAgentRunActivity(
76+ type = " thought" ,
77+ content = {" type" : " thought" , " body" : " Received your request. Analyzing..." },
78+ ),
6879 )
6980
7081 # Now proceed with actual processing
71- result = await process_request(webhook)
72-
82+ result = process_request(webhook)
83+
7384 # ... rest of the logic
7485```
7586
@@ -108,24 +119,29 @@ When a user wants to stop an agent run, Plane sends a `stop` signal with the act
108119<Tab title = " TypeScript" >
109120
110121``` typescript
111- async function handleWebhook(webhook : AgentRunActivityWebhook ) {
122+ async function handleWebhook(webhook : AgentRunActivityWebhook , credentials : { bot_token: string ; workspace_slug: string }) {
123+ const planeClient = new PlaneClient ({
124+ baseUrl: process .env .PLANE_API_URL || ' https://api.plane.so' ,
125+ accessToken: credentials .bot_token ,
126+ });
127+
112128 const signal = webhook .agent_run_activity .signal ;
113129 const agentRunId = webhook .agent_run .id ;
114130
115131 // ALWAYS check for stop signal first
116- if (signal === " stop" ) {
132+ if (signal === ' stop' ) {
117133 // Cancel any ongoing work
118134 cancelOngoingTasks (agentRunId );
119-
135+
120136 // Acknowledge the stop
121- await planeClient .agentRuns .activities .create (workspaceSlug , agentRunId , {
122- type: " response" ,
137+ await planeClient .agentRuns .activities .create (credentials . workspace_slug , agentRunId , {
138+ type: ' response' ,
123139 content: {
124- type: " response" ,
140+ type: ' response' ,
125141 body: " Understood. I've stopped processing your previous request." ,
126142 },
127143 });
128-
144+
129145 return ; // Exit early
130146 }
131147
@@ -137,26 +153,33 @@ async function handleWebhook(webhook: AgentRunActivityWebhook) {
137153<Tab title = " Python" >
138154
139155``` python
140- async def handle_webhook (webhook : dict ):
156+ def handle_webhook (webhook : dict , credentials : dict ):
157+ plane_client = PlaneClient(
158+ base_url = os.getenv(" PLANE_API_URL" , " https://api.plane.so" ),
159+ access_token = credentials[" bot_token" ],
160+ )
161+
141162 signal = webhook[" agent_run_activity" ][" signal" ]
142163 agent_run_id = webhook[" agent_run" ][" id" ]
143164
144165 # ALWAYS check for stop signal first
145166 if signal == " stop" :
146167 # Cancel any ongoing work
147168 cancel_ongoing_tasks(agent_run_id)
148-
169+
149170 # Acknowledge the stop
150171 plane_client.agent_runs.activities.create(
151- workspace_slug = workspace_slug,
152- agent_run_id = agent_run_id,
153- type = " response" ,
154- content = {
155- " type" : " response" ,
156- " body" : " Understood. I've stopped processing your previous request." ,
157- },
172+ workspace_slug = credentials[" workspace_slug" ],
173+ run_id = agent_run_id,
174+ data = CreateAgentRunActivity(
175+ type = " response" ,
176+ content = {
177+ " type" : " response" ,
178+ " body" : " Understood. I've stopped processing your previous request." ,
179+ },
180+ ),
158181 )
159-
182+
160183 return # Exit early
161184
162185 # Continue with normal processing...
@@ -215,23 +238,34 @@ Graceful error handling is crucial for a good user experience.
215238### Always Catch and Report Errors
216239
217240``` typescript
218- async function handleWebhook(webhook : AgentRunActivityWebhook ) {
241+ async function handleWebhook(webhook : AgentRunActivityWebhook , credentials : { bot_token: string ; workspace_slug: string }) {
242+ const planeClient = new PlaneClient ({
243+ baseUrl: process .env .PLANE_API_URL || ' https://api.plane.so' ,
244+ accessToken: credentials .bot_token ,
245+ });
246+
219247 const agentRunId = webhook .agent_run .id ;
220248
221249 try {
222- await createThought (" Processing your request..." );
223-
250+ await planeClient .agentRuns .activities .create (credentials .workspace_slug , agentRunId , {
251+ type: ' thought' ,
252+ content: { type: ' thought' , body: ' Processing your request...' },
253+ });
254+
224255 // Your logic here...
225256 const result = await processRequest (webhook );
226-
227- await createResponse (result );
228-
257+
258+ await planeClient .agentRuns .activities .create (credentials .workspace_slug , agentRunId , {
259+ type: ' response' ,
260+ content: { type: ' response' , body: result },
261+ });
262+
229263 } catch (error ) {
230264 // ALWAYS inform the user about errors
231- await planeClient .agentRuns .activities .create (workspaceSlug , agentRunId , {
232- type: " error" ,
265+ await planeClient .agentRuns .activities .create (credentials . workspace_slug , agentRunId , {
266+ type: ' error' ,
233267 content: {
234- type: " error" ,
268+ type: ' error' ,
235269 body: getUserFriendlyErrorMessage (error ),
236270 },
237271 });
@@ -240,14 +274,14 @@ async function handleWebhook(webhook: AgentRunActivityWebhook) {
240274
241275function getUserFriendlyErrorMessage(error : Error ): string {
242276 // Map technical errors to user-friendly messages
243- if (error .message .includes (" rate limit" )) {
277+ if (error .message .includes (' rate limit' )) {
244278 return " I'm receiving too many requests right now. Please try again in a few minutes." ;
245279 }
246- if (error .message .includes (" timeout" )) {
247- return " The operation took too long. Please try a simpler request or try again later." ;
280+ if (error .message .includes (' timeout' )) {
281+ return ' The operation took too long. Please try a simpler request or try again later.' ;
248282 }
249283 // Generic fallback
250- return " I encountered an unexpected error. Please try again or contact support if the issue persists." ;
284+ return ' I encountered an unexpected error. Please try again or contact support if the issue persists.' ;
251285}
252286```
253287
@@ -272,15 +306,15 @@ For multi-turn conversations, maintain context from previous activities.
272306``` typescript
273307// Get all activities for context
274308const activities = await planeClient .agentRuns .activities .list (
275- workspaceSlug ,
309+ credentials . workspace_slug ,
276310 agentRunId
277311);
278312
279313// Build conversation history
280314const history = activities .results
281- .filter (a => a .type === " prompt" || a .type === " response" )
315+ .filter (a => a .type === ' prompt' || a .type === ' response' )
282316 .map (a => ({
283- role: a .type === " prompt" ? " user" : " assistant" ,
317+ role: a .type === ' prompt' ? ' user' : ' assistant' ,
284318 content: a .content .body ,
285319 }));
286320
0 commit comments