Skip to content

Commit abd7b17

Browse files
fix: format dev tool section
1 parent cff1e67 commit abd7b17

File tree

8 files changed

+357
-319
lines changed

8 files changed

+357
-319
lines changed

docs/dev-tools/agents/best-practices.md

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,23 @@ Send a `thought` activity within the first few seconds of receiving a webhook:
3232
== TypeScript {#typescript}
3333

3434
```typescript
35-
import { PlaneClient } from '@makeplane/plane-node-sdk';
35+
import { PlaneClient } from "@makeplane/plane-node-sdk";
3636

37-
async function handleWebhook(webhook: AgentRunActivityWebhook, credentials: { bot_token: string; workspace_slug: string }) {
37+
async function handleWebhook(
38+
webhook: AgentRunActivityWebhook,
39+
credentials: { bot_token: string; workspace_slug: string }
40+
) {
3841
const planeClient = new PlaneClient({
39-
baseUrl: process.env.PLANE_API_URL || 'https://api.plane.so',
42+
baseUrl: process.env.PLANE_API_URL || "https://api.plane.so",
4043
accessToken: credentials.bot_token,
4144
});
4245

4346
const agentRunId = webhook.agent_run.id;
4447

4548
// IMMEDIATELY acknowledge receipt
4649
await planeClient.agentRuns.activities.create(credentials.workspace_slug, agentRunId, {
47-
type: 'thought',
48-
content: { type: 'thought', body: 'Received your request. Analyzing...' },
50+
type: "thought",
51+
content: { type: "thought", body: "Received your request. Analyzing..." },
4952
});
5053

5154
// Now proceed with actual processing
@@ -85,6 +88,7 @@ def handle_webhook(webhook: dict, credentials: dict):
8588

8689
# ... rest of the logic
8790
```
91+
8892
:::
8993

9094
### Thought activity best practices
@@ -94,13 +98,15 @@ def handle_webhook(webhook: dict, credentials: dict):
9498
- Use thoughts to explain what the agent is doing, not technical details
9599

96100
**Good examples:**
101+
97102
- "Analyzing your question about project timelines..."
98103
- "Searching for relevant work items..."
99104
- "Preparing response with the requested data..."
100105

101106
**Avoid:**
107+
102108
- "Initializing LLM context with temperature 0.7..."
103-
- "Executing database query SELECT * FROM..."
109+
- "Executing database query SELECT \* FROM..."
104110
- Generic messages like "Working..." repeated multiple times
105111

106112
## Acknowledging important signals
@@ -119,25 +125,28 @@ When a user wants to stop an agent run, Plane sends a `stop` signal with the act
119125
== TypeScript {#typescript}
120126

121127
```typescript
122-
async function handleWebhook(webhook: AgentRunActivityWebhook, credentials: { bot_token: string; workspace_slug: string }) {
128+
async function handleWebhook(
129+
webhook: AgentRunActivityWebhook,
130+
credentials: { bot_token: string; workspace_slug: string }
131+
) {
123132
const planeClient = new PlaneClient({
124-
baseUrl: process.env.PLANE_API_URL || 'https://api.plane.so',
133+
baseUrl: process.env.PLANE_API_URL || "https://api.plane.so",
125134
accessToken: credentials.bot_token,
126135
});
127136

128137
const signal = webhook.agent_run_activity.signal;
129138
const agentRunId = webhook.agent_run.id;
130139

131140
// ALWAYS check for stop signal first
132-
if (signal === 'stop') {
141+
if (signal === "stop") {
133142
// Cancel any ongoing work
134143
cancelOngoingTasks(agentRunId);
135144

136145
// Acknowledge the stop
137146
await planeClient.agentRuns.activities.create(credentials.workspace_slug, agentRunId, {
138-
type: 'response',
147+
type: "response",
139148
content: {
140-
type: 'response',
149+
type: "response",
141150
body: "Understood. I've stopped processing your previous request.",
142151
},
143152
});
@@ -183,14 +192,15 @@ def handle_webhook(webhook: dict, credentials: dict):
183192

184193
# Continue with normal processing...
185194
```
195+
186196
:::
187197

188198
### Signal considerations
189199

190-
| Signal | How to Handle |
191-
|--------|---------------|
200+
| Signal | How to Handle |
201+
| ---------- | ----------------------------------------- |
192202
| `continue` | Default behavior, proceed with processing |
193-
| `stop` | Immediately halt and confirm |
203+
| `stop` | Immediately halt and confirm |
194204

195205
## Progress communication
196206

@@ -235,34 +245,36 @@ Graceful error handling is crucial for a good user experience.
235245
### Always catch and report errors
236246

237247
```typescript
238-
async function handleWebhook(webhook: AgentRunActivityWebhook, credentials: { bot_token: string; workspace_slug: string }) {
248+
async function handleWebhook(
249+
webhook: AgentRunActivityWebhook,
250+
credentials: { bot_token: string; workspace_slug: string }
251+
) {
239252
const planeClient = new PlaneClient({
240-
baseUrl: process.env.PLANE_API_URL || 'https://api.plane.so',
253+
baseUrl: process.env.PLANE_API_URL || "https://api.plane.so",
241254
accessToken: credentials.bot_token,
242255
});
243256

244257
const agentRunId = webhook.agent_run.id;
245258

246259
try {
247260
await planeClient.agentRuns.activities.create(credentials.workspace_slug, agentRunId, {
248-
type: 'thought',
249-
content: { type: 'thought', body: 'Processing your request...' },
261+
type: "thought",
262+
content: { type: "thought", body: "Processing your request..." },
250263
});
251264

252265
// Your logic here...
253266
const result = await processRequest(webhook);
254267

255268
await planeClient.agentRuns.activities.create(credentials.workspace_slug, agentRunId, {
256-
type: 'response',
257-
content: { type: 'response', body: result },
269+
type: "response",
270+
content: { type: "response", body: result },
258271
});
259-
260272
} catch (error) {
261273
// ALWAYS inform the user about errors
262274
await planeClient.agentRuns.activities.create(credentials.workspace_slug, agentRunId, {
263-
type: 'error',
275+
type: "error",
264276
content: {
265-
type: 'error',
277+
type: "error",
266278
body: getUserFriendlyErrorMessage(error),
267279
},
268280
});
@@ -271,25 +283,27 @@ async function handleWebhook(webhook: AgentRunActivityWebhook, credentials: { bo
271283

272284
function getUserFriendlyErrorMessage(error: Error): string {
273285
// Map technical errors to user-friendly messages
274-
if (error.message.includes('rate limit')) {
286+
if (error.message.includes("rate limit")) {
275287
return "I'm receiving too many requests right now. Please try again in a few minutes.";
276288
}
277-
if (error.message.includes('timeout')) {
278-
return 'The operation took too long. Please try a simpler request or try again later.';
289+
if (error.message.includes("timeout")) {
290+
return "The operation took too long. Please try a simpler request or try again later.";
279291
}
280292
// Generic fallback
281-
return 'I encountered an unexpected error. Please try again or contact support if the issue persists.';
293+
return "I encountered an unexpected error. Please try again or contact support if the issue persists.";
282294
}
283295
```
284296

285297
### Error message guidelines
286298

287299
**Do:**
300+
288301
- Use clear, non-technical language
289302
- Suggest next steps when possible
290303
- Be honest about what went wrong (at a high level)
291304

292305
**Don't:**
306+
293307
- Expose stack traces or technical details
294308
- Blame the user for errors
295309
- Leave users without any feedback
@@ -302,16 +316,13 @@ For multi-turn conversations, maintain context from previous activities.
302316

303317
```typescript
304318
// Get all activities for context
305-
const activities = await planeClient.agentRuns.activities.list(
306-
credentials.workspace_slug,
307-
agentRunId
308-
);
319+
const activities = await planeClient.agentRuns.activities.list(credentials.workspace_slug, agentRunId);
309320

310321
// Build conversation history
311322
const history = activities.results
312-
.filter(a => a.type === 'prompt' || a.type === 'response')
313-
.map(a => ({
314-
role: a.type === 'prompt' ? 'user' : 'assistant',
323+
.filter((a) => a.type === "prompt" || a.type === "response")
324+
.map((a) => ({
325+
role: a.type === "prompt" ? "user" : "assistant",
315326
content: a.content.body,
316327
}));
317328

@@ -370,21 +381,25 @@ app.post("/webhook", async (req, res) => {
370381
## Summary checklist
371382

372383
**Responsiveness**
384+
373385
- Send thought within seconds of webhook
374386
- Return webhook response quickly
375387
- Send heartbeats for long operations
376388

377389
**Signal handling**
390+
378391
- Always check for `stop` signal first
379392
- Handle all signal types appropriately
380393
- Confirm when stopping
381394

382395
**Error handling**
396+
383397
- Wrap processing in try/catch
384398
- Always send error activity on failure
385399
- Use friendly error messages
386400

387401
**User experience**
402+
388403
- Progress updates for long tasks
389404
- Clear, non-technical communication
390405
- Maintain conversation context

0 commit comments

Comments
 (0)