@theokit/sdk 4.2.6 → 4.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/claude-template/AGENTS.md +73 -55
  3. package/claude-template/CLAUDE.md +16 -1
  4. package/claude-template/dot-claude/rules/theokit-conventions.md +2 -3
  5. package/claude-template/dot-claude/skills/theokit-agent-core/SKILL.md +3 -3
  6. package/claude-template/dot-claude/skills/theokit-auth/SKILL.md +102 -0
  7. package/claude-template/dot-claude/skills/theokit-client/SKILL.md +58 -0
  8. package/claude-template/dot-claude/skills/theokit-compaction/SKILL.md +102 -0
  9. package/claude-template/dot-claude/skills/theokit-concurrency/SKILL.md +68 -0
  10. package/claude-template/dot-claude/skills/theokit-filesystem/SKILL.md +74 -0
  11. package/claude-template/dot-claude/skills/theokit-messages/SKILL.md +58 -0
  12. package/claude-template/dot-claude/skills/theokit-models/SKILL.md +79 -0
  13. package/claude-template/dot-claude/skills/theokit-path-safety/SKILL.md +60 -0
  14. package/claude-template/dot-claude/skills/theokit-persistence/SKILL.md +85 -0
  15. package/claude-template/dot-claude/skills/theokit-project/SKILL.md +55 -0
  16. package/claude-template/dot-claude/skills/theokit-retry/SKILL.md +50 -0
  17. package/claude-template/dot-claude/skills/theokit-sandbox/SKILL.md +93 -0
  18. package/claude-template/dot-claude/skills/theokit-sanitize/SKILL.md +66 -0
  19. package/claude-template/dot-claude/skills/theokit-skills/SKILL.md +68 -0
  20. package/claude-template/dot-claude/skills/theokit-subagents/SKILL.md +109 -0
  21. package/claude-template/dot-claude/skills/theokit-subscriptions/SKILL.md +6 -6
  22. package/claude-template/dot-claude/skills/theokit-task-store/SKILL.md +75 -0
  23. package/claude-template/dot-claude/skills/theokit-tools/SKILL.md +9 -9
  24. package/package.json +1 -1
  25. package/claude-template/dot-claude/skills/theokit-rag/SKILL.md +0 -226
@@ -0,0 +1,68 @@
1
+ ---
2
+ user-invocable: false
3
+ description: Discover SKILL.md packs and render the <skills> block with @theokit/sdk/skills, plus enabling skills on an agent.
4
+ paths:
5
+ - "**/*skill*"
6
+ - "**/*Skill*"
7
+ ---
8
+
9
+ # TheoKit SDK -- Skills
10
+
11
+ `discoverSkills` walks a directory for `<dir>/<name>/SKILL.md` packs, parses strict YAML frontmatter (`name`/`description` required; `category`/`dependencies` optional), skips malformed skills and symlink escapes, and NEVER throws (a missing/unreadable/non-directory path yields `[]`). `buildSkillsBlock` renders the prompt-injection-safe `<skills>` system-prompt block from the discovered list. These are the same primitives the SDK runtime uses internally for `.theokit/skills` discovery.
12
+
13
+ ## Import
14
+
15
+ ```typescript
16
+ import { discoverSkills, buildSkillsBlock } from "@theokit/sdk/skills";
17
+ import type { Skill, DiscoverSkillsOptions, InvalidSkillInfo } from "@theokit/sdk/skills";
18
+ ```
19
+
20
+ ## Signatures
21
+
22
+ ```typescript
23
+ function discoverSkills(dir: string, options?: DiscoverSkillsOptions): Promise<Skill[]>;
24
+ function buildSkillsBlock(
25
+ skills: ReadonlyArray<{ name: string; description: string }>,
26
+ ): string | undefined; // undefined for an empty list
27
+
28
+ interface Skill {
29
+ name: string;
30
+ description: string;
31
+ source: string; // absolute path to the discovered SKILL.md
32
+ category?: string;
33
+ dependencies?: string[];
34
+ }
35
+
36
+ interface DiscoverSkillsOptions {
37
+ onInvalidSkill?: (info: InvalidSkillInfo) => void; // called per malformed SKILL.md
38
+ }
39
+ ```
40
+
41
+ ## Discover and render
42
+
43
+ ```typescript
44
+ const skills = await discoverSkills(".theokit/skills", {
45
+ onInvalidSkill: (info: InvalidSkillInfo) =>
46
+ console.warn(`skipped ${info.name}: ${info.code} — ${info.message}`),
47
+ });
48
+
49
+ // readdir order is OS-dependent; sort for a stable block
50
+ skills.sort((a, b) => a.name.localeCompare(b.name));
51
+
52
+ const block = buildSkillsBlock(skills); // string | undefined
53
+ ```
54
+
55
+ ## Skill packs live at `.theokit/skills/<name>/SKILL.md`
56
+
57
+ Each pack is a directory with a `SKILL.md` whose frontmatter has `name` + `description`. Enable specific packs on an agent by name:
58
+
59
+ ```typescript
60
+ import { Agent } from "@theokit/sdk";
61
+
62
+ const agent = await Agent.create({
63
+ apiKey: process.env.THEOKIT_API_KEY!,
64
+ model: { id: "google/gemini-2.0-flash-001" },
65
+ local: { cwd: process.cwd() },
66
+ skills: { enabled: ["research", "code-review"] },
67
+ });
68
+ ```
@@ -0,0 +1,109 @@
1
+ ---
2
+ user-invocable: false
3
+ paths:
4
+ - "**/*subagent*"
5
+ - "**/*a2a*"
6
+ - "**/*delegat*"
7
+ description: TheoKit SDK subagents — @theokit/sdk/a2a (SubAgent.create, AgentMailbox, MessageBus, delegation hooks) and @theokit/sdk/subagents (subagentToolWhitelist, withSubagentToolScope)
8
+ ---
9
+
10
+ # TheoKit SubAgents
11
+
12
+ Two subpaths cover delegation. `@theokit/sdk/a2a` builds a child agent invocable as
13
+ a tool plus the in-process message bus; `@theokit/sdk/subagents` scopes which tools a
14
+ subagent may call.
15
+
16
+ ```typescript
17
+ import {
18
+ SubAgent,
19
+ AgentMailbox,
20
+ MessageBus,
21
+ MaxDelegationDepthError,
22
+ type SubAgentSpec,
23
+ } from "@theokit/sdk/a2a";
24
+ import { subagentToolWhitelist, withSubagentToolScope } from "@theokit/sdk/subagents";
25
+ ```
26
+
27
+ ## `SubAgent.create` — delegation as a tool
28
+
29
+ `SubAgent.create(spec, parentDepth?)` returns a `CustomTool`. When the LLM invokes it,
30
+ a child agent runs the input as a message. Depth is tracked — exceeding
31
+ `maxDelegationDepth` throws `MaxDelegationDepthError`.
32
+
33
+ ```typescript
34
+ const researcher = SubAgent.create({
35
+ name: "researcher",
36
+ description: "Delegate research questions to a focused child agent",
37
+ instructions: "You research topics and return a concise summary.",
38
+ model: "google/gemini-2.0-flash-001",
39
+ tools: [], // CustomTool[] the child may use
40
+ maxDelegationDepth: 3,
41
+ onDelegationStart: (ctx) => {
42
+ if (ctx.iteration > 5) return { proceed: false, rejectionReason: "too many calls" };
43
+ return { proceed: true };
44
+ },
45
+ onDelegationComplete: (ctx) => {
46
+ if (ctx.result) return { feedback: "(reviewed)" };
47
+ },
48
+ });
49
+
50
+ const agent = await Agent.create({
51
+ apiKey: process.env.THEOKIT_API_KEY!,
52
+ model: { id: "google/gemini-2.0-flash-001" },
53
+ local: { cwd: process.cwd() },
54
+ tools: [researcher],
55
+ });
56
+ ```
57
+
58
+ `SubAgentSpec` also supports `messageFilter` (opt-in parent-context forwarding, off by
59
+ default so memory isolation stays the default) and `includeToolResults` (append the
60
+ child's tool results, otherwise text-only).
61
+
62
+ ## Inline subagents on `Agent.create`
63
+
64
+ Simple cases need no `SubAgent.create` — declare them inline:
65
+
66
+ ```typescript
67
+ const agent = await Agent.create({
68
+ apiKey: process.env.THEOKIT_API_KEY!,
69
+ model: { id: "google/gemini-2.0-flash-001" },
70
+ local: { cwd: process.cwd() },
71
+ agents: {
72
+ reviewer: {
73
+ description: "Reviews code for bugs",
74
+ prompt: "You are a strict code reviewer.",
75
+ model: "google/gemini-2.0-flash-001",
76
+ },
77
+ },
78
+ });
79
+ ```
80
+
81
+ ## Tool scoping — `withSubagentToolScope`
82
+
83
+ `subagentToolWhitelist(definition)` derives the allowed tool-name `Set` (or `undefined`
84
+ when unscoped) from `definition.tools`. `withSubagentToolScope` runs a fn under that
85
+ whitelist so a `tools: ["read_file"]` subagent provably cannot call `write_file`.
86
+
87
+ ```typescript
88
+ const whitelist = subagentToolWhitelist({ tools: ["read_file"] }); // Set(["read_file"])
89
+
90
+ await withSubagentToolScope({ tools: ["read_file"] }, async () => {
91
+ // dispatch veto enforces the whitelist here
92
+ });
93
+ ```
94
+
95
+ ## Agent-to-agent messaging
96
+
97
+ ```typescript
98
+ const bus = new MessageBus();
99
+ const alice = new AgentMailbox("alice", bus);
100
+ const bob = new AgentMailbox("bob", bus);
101
+
102
+ bob.onMessage(async (msg) => ({ type: "ack", payload: { ok: true } }));
103
+
104
+ await alice.send("bob", { type: "greet", payload: { text: "hi" } });
105
+ const reply = await alice.request("bob", { type: "ping", payload: null }, { timeoutMs: 1000 });
106
+
107
+ alice.dispose();
108
+ bob.dispose();
109
+ ```
@@ -5,7 +5,7 @@ paths:
5
5
  - "**/*sse*"
6
6
  - "**/*websocket*"
7
7
  - "**/*ws.*"
8
- description: TheoKit SDK Subscriptions API — defineSubscription, SSE/WebSocket transport, subscribe, tracked, resume tokens
8
+ description: TheoKit SDK Subscriptions API — Subscription.create, SSE/WebSocket transport, subscribe, tracked, resume tokens
9
9
  ---
10
10
 
11
11
  # TheoKit Subscriptions
@@ -13,13 +13,13 @@ description: TheoKit SDK Subscriptions API — defineSubscription, SSE/WebSocket
13
13
  Typed WebSocket + W3C SSE subscriptions with opaque resume tokens. Available
14
14
  via the `@theokit/sdk/subscription` sub-path import (not on the main barrel).
15
15
 
16
- ## Server side — `defineSubscription`
16
+ ## Server side — `Subscription.create`
17
17
 
18
18
  ```typescript
19
- import { defineSubscription } from "@theokit/sdk/subscription";
19
+ import { Subscription } from "@theokit/sdk/subscription";
20
20
  import { z } from "zod";
21
21
 
22
- export default defineSubscription({
22
+ export default Subscription.create({
23
23
  input: z.object({
24
24
  room: z.string(),
25
25
  lastEventId: z.string().optional(),
@@ -91,11 +91,11 @@ for await (const msg of subscribe<
91
91
 
92
92
  ## Composing with LLM streaming
93
93
 
94
- `Agent.streamObject` and `defineSubscription` are independent surfaces. Call
94
+ `Agent.streamObject` and `Subscription.create` are independent surfaces. Call
95
95
  `Agent.streamObject` inside a subscription handler:
96
96
 
97
97
  ```typescript
98
- export default defineSubscription({
98
+ export default Subscription.create({
99
99
  input: z.object({ topic: z.string() }),
100
100
  output: z.object({ kind: z.enum(["partial", "complete"]), text: z.string() }),
101
101
  async *handler(input, ctx) {
@@ -0,0 +1,75 @@
1
+ ---
2
+ user-invocable: false
3
+ paths:
4
+ - "**/*task-store*"
5
+ - "**/*taskstore*"
6
+ - "**/*TaskStore*"
7
+ description: TheoKit SDK task persistence — @theokit/sdk/task-store (TaskStore interface, InMemoryTaskStore, JsonFileTaskStore, getTaskStoreFor factory)
8
+ ---
9
+
10
+ # TheoKit Task Store
11
+
12
+ `@theokit/sdk/task-store` is the storage layer behind the task registry. Pick
13
+ `InMemoryTaskStore` (transient, single-process default) or `JsonFileTaskStore` (one JSON
14
+ file per task under a dir; single-process invariant — v0.2 SQLite covers cross-process).
15
+
16
+ ```typescript
17
+ import {
18
+ getTaskStoreFor,
19
+ InMemoryTaskStore,
20
+ JsonFileTaskStore,
21
+ type TaskStore,
22
+ } from "@theokit/sdk/task-store";
23
+ ```
24
+
25
+ ## The `TaskStore` interface
26
+
27
+ All methods are async. `TaskHandle` / `TaskFilter` come from the main `@theokit/sdk`
28
+ barrel.
29
+
30
+ ```typescript
31
+ interface TaskStore {
32
+ insert(handle: TaskHandle): Promise<void>;
33
+ update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined>;
34
+ get(id: string): Promise<TaskHandle | undefined>;
35
+ list(filter: TaskFilter): Promise<TaskHandle[]>;
36
+ delete(id: string): Promise<boolean>;
37
+ evictTerminalOlderThan(epochMs: number): Promise<number>;
38
+ }
39
+ ```
40
+
41
+ ## Factory — `getTaskStoreFor`
42
+
43
+ Discriminated on `backend`; the `json` backend auto-creates its dir (mkdir recursive).
44
+
45
+ ```typescript
46
+ const memory: TaskStore = getTaskStoreFor({ backend: "memory" });
47
+ const onDisk: TaskStore = getTaskStoreFor({ backend: "json", dir: ".theokit/tasks" });
48
+ ```
49
+
50
+ Or construct directly:
51
+
52
+ ```typescript
53
+ const store = new JsonFileTaskStore(".theokit/tasks"); // constructor(dir: string)
54
+ ```
55
+
56
+ ## Reading tasks
57
+
58
+ `list` returns at most `filter.limit ?? 100` handles; `JsonFileTaskStore` hard-caps
59
+ loaded entries at 256 — page larger timelines via `submittedBefore`.
60
+
61
+ ```typescript
62
+ import type { TaskFilter } from "@theokit/sdk";
63
+
64
+ const filter: TaskFilter = { state: ["running", "queued"], kind: "run", limit: 50 };
65
+ const running = await store.list(filter);
66
+
67
+ for (const h of running) {
68
+ console.log(h.id, h.state, h.submittedAt);
69
+ if (h.cancelRequested) console.log(" (cross-process cancel requested)");
70
+ }
71
+ ```
72
+
73
+ `cancelRequested` is set by the CLI's cross-process best-effort cancel (EC-7); the owning
74
+ process polls it at checkpoints. `evictTerminalOlderThan(epochMs)` removes terminal
75
+ handles older than a cutoff and returns the count removed.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  user-invocable: false
3
- description: Custom tools, defineTool with Zod schemas, and built-in coding tools for @theokit/sdk.
3
+ description: Custom tools, Tool.create with Zod schemas, and built-in coding tools for @theokit/sdk.
4
4
  paths:
5
5
  - "**/*tool*"
6
6
  - "**/*Tool*"
@@ -10,13 +10,13 @@ paths:
10
10
 
11
11
  Quick reference for custom inline tools and built-in coding tools.
12
12
 
13
- ## defineTool (type-safe builder)
13
+ ## Tool.create (type-safe builder)
14
14
 
15
15
  ```typescript
16
16
  import { z } from "zod";
17
- import { defineTool } from "@theokit/sdk";
17
+ import { Tool } from "@theokit/sdk";
18
18
 
19
- const rollTool = defineTool({
19
+ const rollTool = Tool.create({
20
20
  name: "roll",
21
21
  description: "Roll N dice with S sides each.",
22
22
  inputSchema: z.object({
@@ -84,22 +84,22 @@ await agent.send("Use only the calculator.", {
84
84
  // tools: [] -> no custom tools for this run
85
85
  ```
86
86
 
87
- ## Built-in coding tools (`@theokit/sdk/tools`)
87
+ ## Built-in coding tools (`@theokit/sdk-tools`)
88
88
 
89
- Drop-in toolkit for coding agents. All tools are project-scoped and refuse sensitive files.
89
+ Drop-in toolkit for coding agents, shipped as the separate `@theokit/sdk-tools` package (not a `@theokit/sdk/tools` subpath). All tools are project-scoped and refuse sensitive files.
90
90
 
91
91
  ```typescript
92
- import { createAgentFactory } from "@theokit/sdk";
92
+ import { AgentFactory } from "@theokit/sdk";
93
93
  import {
94
94
  createReadFileTool,
95
95
  createListDirTool,
96
96
  createSearchTextTool,
97
97
  createGitDiffTool,
98
98
  createRunVitestTool,
99
- } from "@theokit/sdk/tools";
99
+ } from "@theokit/sdk-tools";
100
100
 
101
101
  const projectRoot = process.cwd();
102
- const factory = createAgentFactory({
102
+ const factory = AgentFactory.create({
103
103
  apiKey: process.env.ANTHROPIC_API_KEY!,
104
104
  model: { id: "claude-sonnet-4-6" },
105
105
  tools: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theokit/sdk",
3
- "version": "4.2.6",
3
+ "version": "4.2.8",
4
4
  "description": "TypeScript SDK for the Theo agent harness — same surface, local or cloud.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/usetheodev/theokit-sdk#readme",
@@ -1,226 +0,0 @@
1
- ---
2
- user-invocable: false
3
- description: RAG primitives -- VectorRetriever, CohereReranker, text splitters from @theokit/sdk/rag.
4
- paths:
5
- - "**/*retriev*"
6
- - "**/*rerank*"
7
- - "**/*splitter*"
8
- - "**/*rag*"
9
- ---
10
-
11
- # TheoKit SDK -- RAG
12
-
13
- Quick reference for the RAG (Retrieval-Augmented Generation) sub-path at `@theokit/sdk/rag`.
14
-
15
- ## Installation
16
-
17
- The RAG module ships with `@theokit/sdk` -- no additional install needed.
18
-
19
- ```typescript
20
- import {
21
- VectorRetriever,
22
- CohereReranker,
23
- NoopReranker,
24
- splitByCharacter,
25
- splitBySentence,
26
- splitRecursive,
27
- } from "@theokit/sdk/rag";
28
- ```
29
-
30
- ## Types
31
-
32
- ```typescript
33
- interface Document {
34
- id: string;
35
- text: string;
36
- metadata?: Record<string, unknown>;
37
- }
38
-
39
- interface Chunk {
40
- text: string;
41
- index: number;
42
- metadata?: Record<string, unknown>;
43
- }
44
-
45
- interface RetrievalResult {
46
- text: string;
47
- score: number;
48
- metadata?: Record<string, unknown>;
49
- }
50
-
51
- interface RankedChunk {
52
- text: string;
53
- score: number;
54
- originalIndex: number;
55
- metadata?: Record<string, unknown>;
56
- }
57
-
58
- interface SplitOptions {
59
- chunkSize: number;
60
- overlap?: number;
61
- }
62
- ```
63
-
64
- ## Interfaces
65
-
66
- ### Retriever
67
-
68
- ```typescript
69
- interface Retriever {
70
- retrieve(query: string, options?: { topK?: number }): Promise<RetrievalResult[]>;
71
- }
72
- ```
73
-
74
- ### Reranker
75
-
76
- ```typescript
77
- interface Reranker {
78
- rerank(query: string, chunks: RetrievalResult[]): Promise<RankedChunk[]>;
79
- }
80
- ```
81
-
82
- ## VectorRetriever
83
-
84
- Wraps any index that implements `search(query, topK)`.
85
-
86
- ```typescript
87
- interface VectorIndex {
88
- search(query: string, topK: number): Promise<RetrievalResult[]>;
89
- }
90
-
91
- interface VectorRetrieverOptions {
92
- index: VectorIndex;
93
- topK?: number; // default 5
94
- }
95
- ```
96
-
97
- Usage:
98
-
99
- ```typescript
100
- import { VectorRetriever } from "@theokit/sdk/rag";
101
-
102
- const retriever = new VectorRetriever({
103
- index: myVectorIndex,
104
- topK: 10,
105
- });
106
-
107
- const results = await retriever.retrieve("How does auth work?");
108
- // results: RetrievalResult[] sorted by relevance
109
- ```
110
-
111
- The `VectorIndex` interface is the DI boundary. Consumers depend on the interface; implementations (e.g., backed by Memory's SQLite-vec or LanceDB index) depend on the index adapter.
112
-
113
- ## CohereReranker
114
-
115
- Calls the Cohere Rerank v2 API to re-score retrieval results by relevance.
116
-
117
- ```typescript
118
- interface CohereRerankerOptions {
119
- apiKey: string;
120
- model?: string; // default "rerank-v3.5"
121
- }
122
- ```
123
-
124
- Usage:
125
-
126
- ```typescript
127
- import { CohereReranker } from "@theokit/sdk/rag";
128
-
129
- const reranker = new CohereReranker({
130
- apiKey: process.env.COHERE_API_KEY!,
131
- model: "rerank-v3.5",
132
- });
133
-
134
- const ranked = await reranker.rerank("auth middleware", retrievalResults);
135
- // ranked: RankedChunk[] re-scored by Cohere
136
- ```
137
-
138
- ## NoopReranker
139
-
140
- Passes through results unchanged. Useful as a baseline or when reranking is not needed.
141
-
142
- ```typescript
143
- import { NoopReranker } from "@theokit/sdk/rag";
144
-
145
- const reranker = new NoopReranker();
146
- const ranked = await reranker.rerank(query, results);
147
- // ranked === results (with originalIndex added)
148
- ```
149
-
150
- ## Text splitters
151
-
152
- Three strategies for splitting documents into chunks. All return `Chunk[]` with `text` and `index`. Empty input returns an empty array.
153
-
154
- ### splitByCharacter
155
-
156
- Fixed-size character windows with optional overlap.
157
-
158
- ```typescript
159
- import { splitByCharacter } from "@theokit/sdk/rag";
160
-
161
- const chunks = splitByCharacter(longText, { chunkSize: 500, overlap: 50 });
162
- ```
163
-
164
- ### splitBySentence
165
-
166
- Groups sentences into chunks up to `chunkSize` characters.
167
-
168
- ```typescript
169
- import { splitBySentence } from "@theokit/sdk/rag";
170
-
171
- const chunks = splitBySentence(longText, { chunkSize: 500 });
172
- ```
173
-
174
- Splits on sentence boundaries (`.`, `!`, `?` followed by whitespace). Sentences are never broken mid-sentence.
175
-
176
- ### splitRecursive
177
-
178
- Three-level cascading split: paragraph, then sentence, then character.
179
-
180
- ```typescript
181
- import { splitRecursive } from "@theokit/sdk/rag";
182
-
183
- const chunks = splitRecursive(longText, { chunkSize: 500, overlap: 50 });
184
- ```
185
-
186
- Algorithm:
187
- 1. Split by double newlines (paragraphs).
188
- 2. Paragraphs that exceed `chunkSize` are split by sentence.
189
- 3. Sentences that still exceed `chunkSize` are split by character.
190
-
191
- This is the recommended default for most RAG use cases.
192
-
193
- ## Full RAG pipeline example
194
-
195
- ```typescript
196
- import { VectorRetriever, CohereReranker, splitRecursive } from "@theokit/sdk/rag";
197
-
198
- // 1. Split documents
199
- const chunks = splitRecursive(documentText, { chunkSize: 500, overlap: 50 });
200
-
201
- // 2. Index chunks (your vector store)
202
- await vectorStore.upsert(chunks.map((c, i) => ({
203
- id: `doc-${i}`,
204
- text: c.text,
205
- embedding: await embed(c.text),
206
- })));
207
-
208
- // 3. Retrieve
209
- const retriever = new VectorRetriever({ index: vectorStore, topK: 20 });
210
- const results = await retriever.retrieve(userQuery);
211
-
212
- // 4. Rerank
213
- const reranker = new CohereReranker({ apiKey: process.env.COHERE_API_KEY! });
214
- const ranked = await reranker.rerank(userQuery, results);
215
-
216
- // 5. Use top results as agent context
217
- const context = ranked.slice(0, 5).map((r) => r.text).join("\n\n");
218
- const agent = await Agent.create({
219
- systemPrompt: `Use this context:\n${context}`,
220
- // ...
221
- });
222
- ```
223
-
224
- ## DI integration
225
-
226
- Use `@Retriever` and `@Reranker` decorators from `@theokit/di-agent` to register RAG components in the DI container. See the theokit-di-agent skill for details.