Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fiery-times-create.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/sdk": minor
---

Changed: BREAKING: Use ModelPreferences instead of an explicit AIModel in AI.prompt(). This supports BYOK and user preferences.
25 changes: 13 additions & 12 deletions agents/chat/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { Type } from "typebox";

import {
type Activity,
ActivityType,
Agent,
AuthorType,
Tag,
Tools,
type Tools,
} from "@plotday/sdk";
import { AI, AIModel, type AIMessage } from "@plotday/sdk/tools/ai";
import { AI, type AIMessage } from "@plotday/sdk/tools/ai";
import { Plot } from "@plotday/sdk/tools/plot";
import { Type } from "typebox";

export default class extends Agent {
private ai: AI;
private plot: Plot;

constructor(protected tools: Tools) {
super();
super(tools);
this.ai = tools.get(AI);
this.plot = tools.get(Plot);
}
Expand All @@ -26,7 +27,7 @@ export default class extends Agent {
previous: Activity;
tagsAdded: Record<number, string[]>;
tagsRemoved: Record<number, string[]>;
},
}
) {
if (changes) return;

Expand All @@ -35,7 +36,7 @@ export default class extends Agent {
if (
activity.note?.includes("@chat") ||
previousActivities.some((activity: any) =>
activity.note.includes("@chat"),
activity.note.includes("@chat")
)
) {
// Add Thinking tag to indicate processing has started
Expand Down Expand Up @@ -63,7 +64,7 @@ You can also create tasks, but should only do so when the user explicitly asks y
? "assistant"
: "user",
content: (prevActivity.note ?? prevActivity.title)!,
}) satisfies AIMessage,
} satisfies AIMessage)
),
];

Expand All @@ -81,7 +82,7 @@ You can also create tasks, but should only do so when the user explicitly asks y
Type.String({
description:
"Optional detailed description of the action item. Can include markdown. Only add when important details are needed beyond the title.",
}),
})
),
title: Type.String({
description:
Expand All @@ -90,13 +91,13 @@ You can also create tasks, but should only do so when the user explicitly asks y
}),
{
description: "Tasks to create in response to the user's request.",
},
),
}
)
),
});

const response = await this.ai.prompt({
model: AIModel.LLAMA_33_70B,
model: { speed: "balanced", cost: "low" },
messages,
outputSchema: schema,
});
Expand All @@ -117,7 +118,7 @@ You can also create tasks, but should only do so when the user explicitly asks y
priority: activity.priority,
type: ActivityType.Task,
start: new Date(),
}),
})
) ?? []),
]);

Expand Down
2 changes: 1 addition & 1 deletion sdk/cli/commands/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export async function generateCommand(options: GenerateOptions) {
try {
out.progress("Generating agent from spec...");

const response = await fetch(`${options.apiUrl}/v1/agent/${agentId}/generate`, {
const response = await fetch(`${options.apiUrl}/v1/agent/generate`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Expand Down
106 changes: 12 additions & 94 deletions sdk/cli/templates/AGENTS.template.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,7 @@ Plot agents are TypeScript classes that extend the `Agent` base class. Agents in
## Agent Structure Pattern

```typescript
import {
type Activity,
Agent,
type Priority,
type Tools,
} from "@plotday/sdk";
import { type Activity, Agent, type Priority, type Tools } from "@plotday/sdk";
import { Plot } from "@plotday/sdk/tools/plot";

export default class MyAgent extends Agent {
Expand Down Expand Up @@ -66,99 +61,22 @@ All `tools.get()` calls must occur in the constructor as they are used for depen

### Built-in Tools (Always Available)

#### Plot Tool
For complete API documentation of built-in tools including all methods, types, and detailed examples, see the TypeScript definitions in your installed package at `node_modules/@plotday/sdk/src/tools/*.ts`. Each tool file contains comprehensive JSDoc documentation.

Core functionality for managing activities:
**Quick reference - Available tools:**

```typescript
import { Plot } from "@plotday/sdk/tools/plot";

// Create activity
await this.plot.createActivity({
type: ActivityType.Task,
title: "Task title",
start: new Date(),
end: null,
links: [], // Optional activity links
parent: { id: "parent-activity-id" }, // Optional parent
});

// Update activity
await this.plot.updateActivity(activityId, {
title: "New title",
completed: true,
});

// Delete activity
await this.plot.deleteActivity(activityId);

// Add contacts
await this.plot.addContacts(contacts);
```

#### Store Tool

Persistent key-value storage (available directly via `this`):

```typescript
// Set value (no import needed)
await this.set("key", value);

// Get value
const value = await this.get<Type>("key");

// Clear value
await this.clear("key");

// Clear all values
await this.clearAll();
```
- `@plotday/sdk/tools/plot` - Core data layer (create/update activities, priorities, contacts)
- `@plotday/sdk/tools/ai` - LLM integration (text generation, structured output, reasoning)
- Use ModelPreferences to specify `speed` (fast/balanced/capable) and `cost` (low/medium/high)
- `@plotday/sdk/tools/store` - Persistent key-value storage (also via `this.set()`, `this.get()`)
- `@plotday/sdk/tools/run` - Queue batched work (also via `this.run()`)
- `@plotday/sdk/tools/callback` - Persistent function references (also via `this.callback()`)
- `@plotday/sdk/tools/auth` - OAuth2 authentication flows
- `@plotday/sdk/tools/webhook` - HTTP webhook management
- `@plotday/sdk/tools/agent` - Manage other agents

**Critical**: Never use instance variables for state. They are lost after function execution. Always use Store methods.

#### Run Tool

Queue separate chunks of work (available directly via `this`):

```typescript
// Create callback and queue execution (no import needed)
const callback = await this.callback("functionName", { context: "data" });
await this.run(callback);

// The function must exist on the agent class
async functionName(args: any, context: { context: string }) {
// Process batch and queue next if needed
if (hasMore) {
const nextCallback = await this.callback("functionName", { context: "next" });
await this.run(nextCallback);
}
}
```

#### Callback Tool

Create persistent function references (for webhooks, auth callbacks - available directly via `this`):

```typescript
// Create callback (no import needed)
const token = await this.callback("onAuthComplete", {
provider: "google",
});

// Pass token to external service or store it
await this.set("webhook_token", token);

// When callback is invoked, your function is called
async onAuthComplete(authResult: any, context?: any) {
// Handle callback
const provider = context?.provider;
}

// Clean up
await this.deleteCallback(token);
await this.deleteAllCallbacks(); // Delete all for this agent
```

### External Tools (Add to package.json)

Add tool dependencies to `package.json`:
Expand Down
4 changes: 4 additions & 0 deletions sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@
"types": "./dist/agents-guide.d.ts",
"default": "./dist/agents-guide.js"
},
"./sdk-docs": {
"types": "./dist/sdk-docs.d.ts",
"default": "./dist/sdk-docs.js"
},
"./tsconfig.base.json": "./tsconfig.base.json"
},
"files": [
Expand Down
100 changes: 12 additions & 88 deletions sdk/src/agents-guide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,99 +80,23 @@ Assign tool instances to class properties for use in other methods.

### Built-in Tools (Always Available)

#### Plot Tool
The following tools are always available to agents. For complete API documentation including all methods, parameters, return types, and detailed examples, refer to the TypeScript definitions which are provided with full JSDoc when generating agents.

Core functionality for managing activities:
**Available Built-in Tools:**
- **Plot** (\`@plotday/sdk/tools/plot\`): Core data layer - create/update activities, priorities, contacts
- **AI** (\`@plotday/sdk/tools/ai\`): LLM access for text generation, structured output, reasoning
- Use ModelPreferences to specify \`speed\` (fast/balanced/capable) and \`cost\` (low/medium/high)
- **Store** (\`@plotday/sdk/tools/store\`): Persistent key-value storage (also available via \`this.set()\`, \`this.get()\`)
- **Run** (\`@plotday/sdk/tools/run\`): Queue batched work (also available via \`this.run()\`)
- **Callback** (\`@plotday/sdk/tools/callback\`): Persistent function references (also available via \`this.callback()\`)
- **Auth** (\`@plotday/sdk/tools/auth\`): OAuth2 authentication flows
- **Webhook** (\`@plotday/sdk/tools/webhook\`): HTTP webhook management
- **AgentManager** (\`@plotday/sdk/tools/agent\`): Manage other agents

\`\`\`typescript
import { Plot } from "@plotday/sdk/tools/plot";

// Create activity
await this.plot.createActivity({
type: ActivityType.Task,
title: "Task title",
start: new Date(),
end: null,
links: [], // Optional activity links
parent: { id: "parent-activity-id" }, // Optional parent
});

// Update activity
await this.plot.updateActivity(activityId, {
title: "New title",
completed: true,
});

// Delete activity
await this.plot.deleteActivity(activityId);

// Add contacts
await this.plot.addContacts(contacts);
\`\`\`

#### Store Tool

Persistent key-value storage (available directly via \`this\`):

\`\`\`typescript
// Set value (no import needed)
await this.set("key", value);

// Get value
const value = await this.get<Type>("key");

// Clear value
await this.clear("key");

// Clear all values
await this.clearAll();
\`\`\`
See the SDK type definitions for full API documentation with usage examples.

**Critical**: Never use instance variables for state. They are lost after function execution. Always use Store methods.

#### Run Tool

Queue separate chunks of work (available directly via \`this\`):

\`\`\`typescript
// Create callback and queue execution (no import needed)
const callback = await this.callback("functionName", { context: "data" });
await this.run(callback);

// The function must exist on the agent class
async functionName(args: any, context: { context: string }) {
// Process batch and queue next if needed
if (hasMore) {
const nextCallback = await this.callback("functionName", { context: "next" });
await this.run(nextCallback);
}
}
\`\`\`

#### Callback Tool

Create persistent function references (for webhooks, auth callbacks - available directly via \`this\`):

\`\`\`typescript
// Create callback (no import needed)
const token = await this.callback("onAuthComplete", {
provider: "google",
});

// Pass token to external service or store it
await this.set("webhook_token", token);

// When callback is invoked, your function is called
async onAuthComplete(authResult: any, context?: any) {
// Handle callback
const provider = context?.provider;
}

// Clean up
await this.deleteCallback(token);
await this.deleteAllCallbacks(); // Delete all for this agent
\`\`\`

### External Tools (Add to package.json)

Add tool dependencies to \`package.json\`:
Expand Down
1 change: 1 addition & 0 deletions sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./agent";
export * from "./plot";
export * from "./tag";
export * from "./tools";
export { getSDKDocumentation } from "./sdk-docs";
Loading