@tangle-network/agent-interface 2.10.0 → 2.11.0

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.
package/README.md CHANGED
@@ -172,6 +172,30 @@ When caller environment values merge into a bridge or harness process, reject na
172
172
  Use `isCredentialBearingProfileConfigName(name)` before retaining public config.
173
173
  These checks do not apply to a replacement environment owned by caller code.
174
174
 
175
+ ## Profile knowledge base
176
+
177
+ `@tangle-network/agent-interface/profile-kb` holds how to get the best from each frontier harness and model this platform runs.
178
+ Every entry cites a vendor source or a command run on a dated check.
179
+ Guidance is specific to one harness or model and never compares models.
180
+
181
+ `withProfileKb(profile)` composes harness guidance, then model guidance, then the profile's own text into the profile's prompt:
182
+
183
+ ```ts
184
+ import { withProfileKb } from "@tangle-network/agent-interface/profile-kb";
185
+
186
+ const worker = withProfileKb({
187
+ harness: "claude-code",
188
+ model: { default: "claude-opus-5-5" },
189
+ prompt: { appendSystemPrompt: "Cite the file you read." },
190
+ });
191
+ ```
192
+
193
+ Guidance goes into `appendSystemPrompt` where the harness owns an additive system-prompt control, and into `instructions` otherwise.
194
+ Recomposing replaces earlier guidance, so a second call, or a call with an executor's harness or model override, yields a stable profile.
195
+ `composeAgentProfileGuidance` is the underlying composer for other knowledge layers.
196
+
197
+ The module also exports the data (`profileKbHarnesses`, `profileKbModels`), operator notes for launching each harness and model, platform learnings (admitted only after an agent-eval check reproduced them), and `profileKbDiscrepancies`, which records where a vendor source states a requested name differently.
198
+
175
199
  ## Failed execution accounting
176
200
 
177
201
  An adapter can reject with `AgentExecutionError` and retain observed usage and timing in its immutable `receipt`.
@@ -519,4 +519,35 @@ export interface AgentProfileValidationResult {
519
519
  * base-first with a blank line between them.
520
520
  */
521
521
  export declare function mergeAgentProfiles(base: AgentProfile | undefined, overlay: AgentProfile | undefined): AgentProfile | undefined;
522
+ /**
523
+ * One block of standing guidance composed into a profile's prompt.
524
+ *
525
+ * `source` names the layer the text came from (`harness`, `model`, or another
526
+ * knowledge layer) and `id` names the subject, so a composed block can be
527
+ * found and replaced later. The profile's own prompt text is never a block:
528
+ * it is what the blocks are composed in front of.
529
+ */
530
+ export interface AgentProfileGuidanceBlock {
531
+ source: string;
532
+ id: string;
533
+ text: string;
534
+ }
535
+ /**
536
+ * Where composed guidance lands. `appendSystemPrompt` keeps the harness's
537
+ * system prompt and adds the guidance to it; `instructions` uses the
538
+ * harness's caller-instruction surface, for harnesses that own no additive
539
+ * system-prompt control.
540
+ */
541
+ export type AgentProfileGuidanceChannel = "appendSystemPrompt" | "instructions";
542
+ /**
543
+ * Compose harness, model, and other layered guidance into a profile's prompt.
544
+ *
545
+ * The blocks come first, in the order given, and the profile's own text comes
546
+ * last, so the most specific instruction (the profile's) is the one a model
547
+ * reads after the general guidance. Composition replaces any blocks a previous
548
+ * composition added, on both channels, so recomposing after a harness or
549
+ * model change never stacks stale guidance. Composing the same blocks twice
550
+ * yields the same profile, and with it the same canonical identity.
551
+ */
552
+ export declare function composeAgentProfileGuidance(profile: AgentProfile, blocks: readonly AgentProfileGuidanceBlock[], channel: AgentProfileGuidanceChannel): AgentProfile;
522
553
  export {};
@@ -173,3 +173,62 @@ export function mergeAgentProfiles(base, overlay) {
173
173
  extensions: mergeRecord(base?.extensions, overlay?.extensions),
174
174
  });
175
175
  }
176
+ const GUIDANCE_OPEN = /^<profile-guidance source="[^"]*" id="[^"]*">\n/;
177
+ const GUIDANCE_BLOCK = /<profile-guidance source="[^"]*" id="[^"]*">\n[\s\S]*?\n<\/profile-guidance>(\n\n)?/g;
178
+ function renderGuidanceBlock(block) {
179
+ if (/["\n]/.test(block.source) || /["\n]/.test(block.id)) {
180
+ throw new TypeError("profile guidance source and id must not contain quotes or newlines");
181
+ }
182
+ if (block.text.includes("</profile-guidance>")) {
183
+ throw new TypeError("profile guidance text must not contain the closing block marker");
184
+ }
185
+ return `<profile-guidance source="${block.source}" id="${block.id}">\n${block.text}\n</profile-guidance>`;
186
+ }
187
+ /** Remove every previously composed guidance block from appended prompt text. */
188
+ function stripGuidanceText(text) {
189
+ if (text === undefined || text === "")
190
+ return text;
191
+ const stripped = text.replace(GUIDANCE_BLOCK, "");
192
+ return stripped === "" ? undefined : stripped;
193
+ }
194
+ /**
195
+ * Compose harness, model, and other layered guidance into a profile's prompt.
196
+ *
197
+ * The blocks come first, in the order given, and the profile's own text comes
198
+ * last, so the most specific instruction (the profile's) is the one a model
199
+ * reads after the general guidance. Composition replaces any blocks a previous
200
+ * composition added, on both channels, so recomposing after a harness or
201
+ * model change never stacks stale guidance. Composing the same blocks twice
202
+ * yields the same profile, and with it the same canonical identity.
203
+ */
204
+ export function composeAgentProfileGuidance(profile, blocks, channel) {
205
+ const prompt = profile.prompt ?? {};
206
+ const ownAppend = stripGuidanceText(prompt.appendSystemPrompt);
207
+ const ownInstructions = prompt.instructions?.filter((line) => !GUIDANCE_OPEN.test(line));
208
+ const rendered = blocks.map(renderGuidanceBlock);
209
+ const next = { ...prompt };
210
+ delete next.appendSystemPrompt;
211
+ delete next.instructions;
212
+ if (channel === "appendSystemPrompt") {
213
+ const parts = [...rendered, ...(ownAppend ? [ownAppend] : [])];
214
+ if (parts.length > 0)
215
+ next.appendSystemPrompt = parts.join("\n\n");
216
+ else if (ownAppend !== undefined)
217
+ next.appendSystemPrompt = ownAppend;
218
+ if (ownInstructions !== undefined)
219
+ next.instructions = ownInstructions;
220
+ }
221
+ else {
222
+ if (ownAppend !== undefined)
223
+ next.appendSystemPrompt = ownAppend;
224
+ const lines = [...rendered, ...(ownInstructions ?? [])];
225
+ if (lines.length > 0 || prompt.instructions !== undefined) {
226
+ next.instructions = lines;
227
+ }
228
+ }
229
+ const result = { ...profile };
230
+ if (Object.keys(next).length > 0 || profile.prompt !== undefined) {
231
+ result.prompt = next;
232
+ }
233
+ return result;
234
+ }
@@ -0,0 +1,9 @@
1
+ import type { ProfileKbHarness } from "./types.js";
2
+ /**
3
+ * The frontier coding harnesses this platform runs, checked against the
4
+ * installed CLI on 2026-09-22.
5
+ *
6
+ * `prompt` lines go into the agent's prompt; `operator` lines are launch
7
+ * facts. Each harness is described on its own terms.
8
+ */
9
+ export declare const profileKbHarnesses: readonly ProfileKbHarness[];
@@ -0,0 +1,115 @@
1
+ const CHECKED = "2026-09-22";
2
+ /**
3
+ * The frontier coding harnesses this platform runs, checked against the
4
+ * installed CLI on 2026-09-22.
5
+ *
6
+ * `prompt` lines go into the agent's prompt; `operator` lines are launch
7
+ * facts. Each harness is described on its own terms.
8
+ */
9
+ export const profileKbHarnesses = [
10
+ {
11
+ id: "claude-code",
12
+ name: "Claude Code",
13
+ version: "2.1.280",
14
+ sources: [
15
+ {
16
+ url: "https://code.claude.com/docs/en/cli-reference",
17
+ checkedAt: CHECKED,
18
+ },
19
+ { url: "cli:claude --help", checkedAt: CHECKED, note: "2.1.280" },
20
+ ],
21
+ prompt: [
22
+ "Delegate independent slices to subagents, several in one turn so they run in parallel, then synthesize their results.",
23
+ "Use the skills listed in your session for procedures they cover.",
24
+ "Run long commands in the background and keep working while they finish.",
25
+ ],
26
+ operator: [
27
+ "Headless: `claude -p <prompt> --model <id> --effort <level> --output-format stream-json`.",
28
+ "`--append-system-prompt` adds to the built-in prompt; `--system-prompt` replaces it.",
29
+ "`--max-budget-usd` caps spend; `--json-schema` validates structured output; `--mcp-config` loads MCP servers.",
30
+ "`--bg` starts a background session; `--bare` skips hooks, plugins, memory, and CLAUDE.md discovery.",
31
+ ],
32
+ },
33
+ {
34
+ id: "codex",
35
+ name: "Codex CLI",
36
+ version: "0.152.1",
37
+ sources: [
38
+ { url: "https://learn.chatgpt.com/docs/models", checkedAt: CHECKED },
39
+ {
40
+ url: "cli:codex exec --help; codex features list",
41
+ checkedAt: CHECKED,
42
+ note: "0.152.1; multi_agent stable and enabled",
43
+ },
44
+ ],
45
+ prompt: [
46
+ "Split independent work across child agents with spawn_agent, and join them with wait_agent.",
47
+ "Edit with apply_patch and search with rg.",
48
+ "Carry the task end to end in this turn: gather context, implement, run the checks, and report the evidence.",
49
+ ],
50
+ operator: [
51
+ "Headless: `codex exec <prompt> -m <model> -c model_reasoning_effort=<level> --json -o <last-message-file>`.",
52
+ "`--output-schema <file>` enforces structured output. `codex review` runs a non-interactive review.",
53
+ "Reasoning levels are per model; read them from `$CODEX_HOME/models_cache.json`.",
54
+ "System-prompt replacement uses the `model_instructions_file` config key; standing instructions go in AGENTS.md.",
55
+ "`/goal` runs long unattended work; `resume` and `fork` continue a session.",
56
+ ],
57
+ },
58
+ {
59
+ id: "opencode",
60
+ name: "OpenCode",
61
+ version: "1.18.18",
62
+ sources: [
63
+ { url: "https://opencode.ai/docs/cli/", checkedAt: CHECKED },
64
+ { url: "cli:opencode run --help", checkedAt: CHECKED, note: "1.18.18" },
65
+ ],
66
+ prompt: [
67
+ "Delegate a focused subtask to a named agent when its persona or model fits the subtask.",
68
+ "Use the mounted MCP tools for external actions.",
69
+ ],
70
+ operator: [
71
+ "Headless: `opencode run <message> -m <provider/model> --agent <name> --variant <effort> --format json`.",
72
+ "Standing text goes through `instructions` files or appended system text; the built-in prompt stays in place.",
73
+ "`opencode serve` with `run --attach <url>`, or `opencode acp`, gives a parent live control.",
74
+ ],
75
+ },
76
+ {
77
+ id: "pi",
78
+ name: "Pi",
79
+ version: "0.83.0",
80
+ sources: [
81
+ { url: "cli:pi --help", checkedAt: CHECKED, note: "0.83.0" },
82
+ ],
83
+ prompt: [
84
+ "Expect steering messages mid-run and fold each one into the current plan.",
85
+ "Fan out independent work by running `pi -p <task> --mode json` from bash, several at once, and read the results back.",
86
+ ],
87
+ operator: [
88
+ "Headless: `pi -p <prompt> --model <provider/id[:thinking]> --mode json`.",
89
+ "`--mode rpc` takes JSONL commands on stdin (steer, follow-up, set model, compact, fork) for live control.",
90
+ "`--thinking` takes off, minimal, low, medium, high, xhigh, or max.",
91
+ "`--system-prompt` replaces the default; `--append-system-prompt` adds to it.",
92
+ ],
93
+ },
94
+ {
95
+ id: "kimi-code",
96
+ name: "Kimi Code CLI",
97
+ version: "0.36.1",
98
+ sources: [
99
+ { url: "https://moonshotai.github.io/kimi-code/", checkedAt: CHECKED },
100
+ {
101
+ url: "cli:kimi --help; ~/.kimi-code/config.toml",
102
+ checkedAt: CHECKED,
103
+ note: "0.36.1",
104
+ },
105
+ ],
106
+ prompt: [
107
+ "Plan the change first, then edit and verify each step against tests and runtime output.",
108
+ ],
109
+ operator: [
110
+ "Headless: `kimi -p <prompt> -m kimi-code/k3 --output-format stream-json`.",
111
+ "`--auto` runs fully autonomous; `--agent-file <path>` loads an agent definition; `--plan` starts in plan mode.",
112
+ "Effort is the `[thinking] effort` key in `~/.kimi-code/config.toml`: low, high, or max.",
113
+ ],
114
+ },
115
+ ];
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Profile knowledge base: how to get the best from each frontier harness and
3
+ * model this platform runs, from current vendor sources, composed into an
4
+ * {@link AgentProfile}'s prompt.
5
+ *
6
+ * The data is plain, dated, and sourced. Composition is pure: the same profile
7
+ * yields the same composed profile, so profile identity stays deterministic.
8
+ */
9
+ import { type AgentProfile, type AgentProfileGuidanceBlock } from "../agent-profile.js";
10
+ import type { HarnessType } from "../harness.js";
11
+ import { profileKbHarnesses } from "./harnesses.js";
12
+ import { profileKbModels } from "./models.js";
13
+ import { profileKbDiscrepancies, profileKbLearnings } from "./records.js";
14
+ import type { ProfileKbHarness, ProfileKbModel } from "./types.js";
15
+ export type * from "./types.js";
16
+ export { profileKbDiscrepancies, profileKbHarnesses, profileKbLearnings, profileKbModels, };
17
+ /** Date the knowledge base was last checked against its sources. */
18
+ export declare const PROFILE_KB_CHECKED_AT = "2026-09-22";
19
+ /** Find a harness entry by its {@link HarnessType}. */
20
+ export declare function findProfileKbHarness(harness: HarnessType | string | undefined): ProfileKbHarness | undefined;
21
+ /**
22
+ * Find a model entry by id or alias.
23
+ *
24
+ * Accepts the spellings harnesses and routers use: a provider prefix
25
+ * (`anthropic/claude-opus-5-5`), a route prefix
26
+ * (`pi/tangle-router/deepseek/deepseek-v4.1-flash`), and a trailing `:suffix`
27
+ * such as pi's thinking level or a router's `:batch`. A different version is a
28
+ * different model and never matches.
29
+ */
30
+ export declare function findProfileKbModel(model: string | undefined): ProfileKbModel | undefined;
31
+ /** Which harness and model to compose guidance for. */
32
+ export interface ProfileKbSelection {
33
+ harness?: HarnessType | string;
34
+ model?: string;
35
+ }
36
+ /**
37
+ * The guidance blocks for one harness and model: the harness's, then the
38
+ * model's, then any reproduced platform learnings for either. Unknown names
39
+ * contribute nothing.
40
+ */
41
+ export declare function profileKbGuidance(selection: ProfileKbSelection): AgentProfileGuidanceBlock[];
42
+ /**
43
+ * Compose harness, model, and profile guidance into the profile's prompt.
44
+ *
45
+ * The harness and model default to the profile's own `harness` and
46
+ * `model.default`; pass a selection to compose for an executor's override.
47
+ * Guidance goes into `appendSystemPrompt` where the harness owns an additive
48
+ * system-prompt control and into `instructions` otherwise, so a harness that
49
+ * refuses appended system text still receives it. The profile's own text
50
+ * stays last. Recomposing replaces earlier guidance, so the result is stable.
51
+ */
52
+ export declare function withProfileKb(profile: AgentProfile, selection?: ProfileKbSelection): AgentProfile;
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Profile knowledge base: how to get the best from each frontier harness and
3
+ * model this platform runs, from current vendor sources, composed into an
4
+ * {@link AgentProfile}'s prompt.
5
+ *
6
+ * The data is plain, dated, and sourced. Composition is pure: the same profile
7
+ * yields the same composed profile, so profile identity stays deterministic.
8
+ */
9
+ import { composeAgentProfileGuidance, } from "../agent-profile.js";
10
+ import { harnessSystemPromptIntents } from "../harness-capabilities.js";
11
+ import { profileKbHarnesses } from "./harnesses.js";
12
+ import { profileKbModels } from "./models.js";
13
+ import { profileKbDiscrepancies, profileKbLearnings } from "./records.js";
14
+ export { profileKbDiscrepancies, profileKbHarnesses, profileKbLearnings, profileKbModels, };
15
+ /** Date the knowledge base was last checked against its sources. */
16
+ export const PROFILE_KB_CHECKED_AT = "2026-09-22";
17
+ /** Find a harness entry by its {@link HarnessType}. */
18
+ export function findProfileKbHarness(harness) {
19
+ if (!harness)
20
+ return undefined;
21
+ return profileKbHarnesses.find((entry) => entry.id === harness);
22
+ }
23
+ const modelIndex = (() => {
24
+ const index = new Map();
25
+ for (const model of profileKbModels) {
26
+ for (const name of [model.id, ...model.aliases]) {
27
+ const key = name.toLowerCase();
28
+ if (index.has(key)) {
29
+ throw new Error(`profile-kb: model name ${name} is declared twice`);
30
+ }
31
+ index.set(key, model);
32
+ }
33
+ }
34
+ return index;
35
+ })();
36
+ /**
37
+ * Find a model entry by id or alias.
38
+ *
39
+ * Accepts the spellings harnesses and routers use: a provider prefix
40
+ * (`anthropic/claude-opus-5-5`), a route prefix
41
+ * (`pi/tangle-router/deepseek/deepseek-v4.1-flash`), and a trailing `:suffix`
42
+ * such as pi's thinking level or a router's `:batch`. A different version is a
43
+ * different model and never matches.
44
+ */
45
+ export function findProfileKbModel(model) {
46
+ if (!model)
47
+ return undefined;
48
+ const colon = model.lastIndexOf(":");
49
+ let candidate = (colon > 0 ? model.slice(0, colon) : model)
50
+ .trim()
51
+ .toLowerCase();
52
+ for (;;) {
53
+ const found = modelIndex.get(candidate);
54
+ if (found)
55
+ return found;
56
+ const slash = candidate.indexOf("/");
57
+ if (slash < 0)
58
+ return undefined;
59
+ candidate = candidate.slice(slash + 1);
60
+ }
61
+ }
62
+ function learningsFor(harness, model) {
63
+ return profileKbLearnings.filter((learning) => {
64
+ const scope = learning.appliesTo;
65
+ if (scope.harness !== undefined && scope.harness !== harness?.id) {
66
+ return false;
67
+ }
68
+ if (scope.model !== undefined && scope.model !== model?.id)
69
+ return false;
70
+ return scope.harness !== undefined || scope.model !== undefined;
71
+ });
72
+ }
73
+ function bullets(lines) {
74
+ return lines.map((line) => `- ${line}`).join("\n");
75
+ }
76
+ /**
77
+ * The guidance blocks for one harness and model: the harness's, then the
78
+ * model's, then any reproduced platform learnings for either. Unknown names
79
+ * contribute nothing.
80
+ */
81
+ export function profileKbGuidance(selection) {
82
+ const harness = findProfileKbHarness(selection.harness);
83
+ const model = findProfileKbModel(selection.model);
84
+ const blocks = [];
85
+ if (harness && harness.prompt.length > 0) {
86
+ blocks.push({
87
+ source: "harness",
88
+ id: harness.id,
89
+ text: `You are running in ${harness.name}.\n${bullets(harness.prompt)}`,
90
+ });
91
+ }
92
+ if (model && model.prompt.length > 0) {
93
+ blocks.push({
94
+ source: "model",
95
+ id: model.id,
96
+ text: `You are ${model.name}.\n${bullets(model.prompt)}`,
97
+ });
98
+ }
99
+ const learnings = learningsFor(harness, model);
100
+ if (learnings.length > 0) {
101
+ blocks.push({
102
+ source: "learning",
103
+ id: learnings.map((learning) => learning.id).join(","),
104
+ text: bullets(learnings.map((learning) => learning.text)),
105
+ });
106
+ }
107
+ return blocks;
108
+ }
109
+ /**
110
+ * Compose harness, model, and profile guidance into the profile's prompt.
111
+ *
112
+ * The harness and model default to the profile's own `harness` and
113
+ * `model.default`; pass a selection to compose for an executor's override.
114
+ * Guidance goes into `appendSystemPrompt` where the harness owns an additive
115
+ * system-prompt control and into `instructions` otherwise, so a harness that
116
+ * refuses appended system text still receives it. The profile's own text
117
+ * stays last. Recomposing replaces earlier guidance, so the result is stable.
118
+ */
119
+ export function withProfileKb(profile, selection = {}) {
120
+ const harness = selection.harness ?? profile.harness;
121
+ const model = selection.model ?? profile.model?.default;
122
+ const blocks = profileKbGuidance({ harness, model });
123
+ const channel = harnessSystemPromptIntents(findProfileKbHarness(harness)?.id ?? harness).append
124
+ ? "appendSystemPrompt"
125
+ : "instructions";
126
+ return composeAgentProfileGuidance(profile, blocks, channel);
127
+ }
@@ -0,0 +1,9 @@
1
+ import type { ProfileKbModel } from "./types.js";
2
+ /**
3
+ * Current frontier models, from vendor sources read on 2026-09-22.
4
+ *
5
+ * `prompt` lines go into the model's prompt; `operator` lines configure the
6
+ * run. Vendor facts carry their source. Nothing here compares one model with
7
+ * another.
8
+ */
9
+ export declare const profileKbModels: readonly ProfileKbModel[];
@@ -0,0 +1,321 @@
1
+ const CHECKED = "2026-09-22";
2
+ const claudeDocs = "https://platform.claude.com/docs/en";
3
+ /**
4
+ * Current frontier models, from vendor sources read on 2026-09-22.
5
+ *
6
+ * `prompt` lines go into the model's prompt; `operator` lines configure the
7
+ * run. Vendor facts carry their source. Nothing here compares one model with
8
+ * another.
9
+ */
10
+ export const profileKbModels = [
11
+ {
12
+ id: "claude-opus-5-5",
13
+ name: "Claude Opus 5.5",
14
+ vendor: "Anthropic",
15
+ surfaces: ["api", "router"],
16
+ aliases: ["anthropic/claude-opus-5-5", "anthropic.claude-opus-5-5"],
17
+ defaultEffort: "medium",
18
+ sources: [
19
+ { url: `${claudeDocs}/models/opus-5-5/overview`, checkedAt: CHECKED },
20
+ {
21
+ url: `${claudeDocs}/build-with-claude/prompt-engineering/prompting-claude-opus-5-5`,
22
+ checkedAt: CHECKED,
23
+ },
24
+ {
25
+ url: "https://www.anthropic.com/claude-opus-5-5-system-card",
26
+ checkedAt: CHECKED,
27
+ note: "system card, linked from the model overview",
28
+ },
29
+ ],
30
+ prompt: [
31
+ "Keep the task's parts in a checklist you update, and keep working until every item is done or blocked.",
32
+ "Put status notes and recommendations in the same message as your next tool call; end the turn only when the work is complete or nothing can move without the user.",
33
+ "Before acting on a loosely specified task, explore the relevant files, records, and sources, including ones the task does not name, and use what you find.",
34
+ "When a lead agent can delegate, run independent slices in parallel subagents and pace the work to finish early.",
35
+ "For dense charts, diagrams, or screenshots, crop and zoom with the available image tools before reading values.",
36
+ ],
37
+ operator: [
38
+ "Model id claude-opus-5-5; 1M context, 128K max output; released 2026-09-22.",
39
+ "Adaptive thinking is always on. Start at effort medium, measure low for cost, and reserve xhigh and max for measured gains.",
40
+ "Set max_tokens to 128000 for long agentic turns: thinking counts toward it.",
41
+ "Keep history append-only and pass thinking blocks back unchanged; change instructions with mid-conversation system messages.",
42
+ "Set thinking display to updates to receive progress notes between tool calls.",
43
+ "For unattended loops, treat a text-only end of turn as a report: name the open items in a short user message, at most two or three times.",
44
+ "For multi-agent runs, append elapsed time against a budget (for example `elapsed 340s / 1200s`) to each message.",
45
+ ],
46
+ },
47
+ {
48
+ id: "claude-fable-5-1",
49
+ name: "Claude Fable 5.1",
50
+ vendor: "Anthropic",
51
+ surfaces: ["api", "router"],
52
+ aliases: ["anthropic/claude-fable-5-1", "anthropic.claude-fable-5-1"],
53
+ defaultEffort: "high",
54
+ sources: [
55
+ { url: `${claudeDocs}/models/fable-5-1/overview`, checkedAt: CHECKED },
56
+ {
57
+ url: `${claudeDocs}/build-with-claude/prompt-engineering/prompting-claude-fable-5-1`,
58
+ checkedAt: CHECKED,
59
+ },
60
+ ],
61
+ prompt: [
62
+ "You are operating autonomously: for reversible actions that follow from the request, proceed without asking; stop only for destructive actions or scope changes the user must decide.",
63
+ "Before ending your turn, check your last paragraph: if it is a plan, a list of next steps, or a promise, do that work now with tool calls.",
64
+ "The request sets the scope: deliver all of it, keep changes to what it needs, and report other findings as follow-ups.",
65
+ "First privately list what you need next; then request every item that does not depend on another's result in one response.",
66
+ "Say in a line what you are about to do, give brief updates while you work, and close with a recap that stands on its own.",
67
+ "Edit files surgically when a targeted edit gives the same result.",
68
+ "Write plainly: when a literal phrase is available, use it.",
69
+ ],
70
+ operator: [
71
+ "Model id claude-fable-5-1; 1M context, 128K max output; released 2026-09-01. For demanding reasoning and long-horizon agentic work.",
72
+ "Adaptive thinking only. Start at effort high and sweep low, medium, xhigh, and max against your evals.",
73
+ "Keep history append-only; send per-turn reminders as turn-scoped system messages (clear_at next_user_message).",
74
+ "Let the lead agent keep working while subagents run: return from the spawn tool immediately and deliver results in a later user message.",
75
+ "At xhigh and max, leave max_tokens room for thinking plus the deliverable.",
76
+ ],
77
+ },
78
+ {
79
+ id: "claude-sonnet-5",
80
+ name: "Claude Sonnet 5",
81
+ vendor: "Anthropic",
82
+ surfaces: ["api", "router"],
83
+ aliases: ["anthropic/claude-sonnet-5", "anthropic.claude-sonnet-5"],
84
+ defaultEffort: "high",
85
+ sources: [
86
+ { url: `${claudeDocs}/models/overview`, checkedAt: CHECKED },
87
+ {
88
+ url: `${claudeDocs}/build-with-claude/prompt-engineering/prompting-claude-sonnet-5`,
89
+ checkedAt: CHECKED,
90
+ },
91
+ ],
92
+ prompt: [
93
+ "Apply each instruction to every case it names; where an instruction should apply broadly, the prompt says so.",
94
+ "For review work, report every issue you find with a confidence and severity; a later step filters them.",
95
+ "Give regular, short progress updates through long agentic work.",
96
+ ],
97
+ operator: [
98
+ "Model id claude-sonnet-5; 1M context, 128K max output.",
99
+ "Adaptive thinking is on by default. Effort defaults to high; use xhigh for the hardest coding and agentic tasks.",
100
+ "Instructions are followed literally, especially at low effort: state scope explicitly.",
101
+ "Give the task, intent, and constraints up front in the first turn.",
102
+ "Temperature, top_p, and top_k stay at defaults; steer tone and variety in the prompt.",
103
+ ],
104
+ },
105
+ {
106
+ id: "claude-haiku-4-5",
107
+ name: "Claude Haiku 4.5",
108
+ vendor: "Anthropic",
109
+ surfaces: ["api", "router"],
110
+ aliases: [
111
+ "claude-haiku-4-5-20251001",
112
+ "anthropic/claude-haiku-4-5",
113
+ "anthropic.claude-haiku-4-5",
114
+ ],
115
+ sources: [
116
+ { url: `${claudeDocs}/models/haiku-4-5/overview`, checkedAt: CHECKED },
117
+ ],
118
+ prompt: [
119
+ "Answer directly and keep each step scoped to the task in hand.",
120
+ ],
121
+ operator: [
122
+ "Model id claude-haiku-4-5-20251001 (alias claude-haiku-4-5); 200K context, 64K max output. The fastest model in the current lineup.",
123
+ "Uses manual extended thinking (thinking.type enabled with budget_tokens); it takes no effort parameter.",
124
+ "Retirement not sooner than 2026-10-15.",
125
+ ],
126
+ },
127
+ {
128
+ id: "gpt-6-pro",
129
+ name: "GPT-6 Pro",
130
+ vendor: "OpenAI",
131
+ surfaces: ["chatgpt"],
132
+ aliases: ["GPT-6 Pro"],
133
+ sources: [
134
+ {
135
+ url: "https://help.openai.com/en/articles/20001354-gpt-56-and-gpt-6-pro-in-chatgpt",
136
+ checkedAt: CHECKED,
137
+ note: "read through search results; direct fetch returned HTTP 403",
138
+ },
139
+ { url: "https://learn.chatgpt.com/docs/prompting", checkedAt: CHECKED },
140
+ ],
141
+ prompt: [
142
+ "Start with the result you want, then give the goal, the context that helps, the output format, and what must stay unchanged.",
143
+ "Describe a process only when the process itself matters; otherwise leave room to search, compare, and adjust.",
144
+ "End with a final check: confirm each deliverable and flag anything you could not verify.",
145
+ ],
146
+ operator: [
147
+ "A ChatGPT model mode powered by GPT-6 Astra, on Pro, Business, and Enterprise plans. It has a weekly usage limit.",
148
+ "No API model id; reach it through ChatGPT (chatgpt-fleet).",
149
+ ],
150
+ },
151
+ {
152
+ id: "gpt-5.6-sol",
153
+ name: "GPT-5.6 Sol",
154
+ vendor: "OpenAI",
155
+ surfaces: ["codex", "api", "router"],
156
+ aliases: ["openai/gpt-5.6-sol"],
157
+ defaultEffort: "medium",
158
+ sources: [
159
+ {
160
+ url: "https://developers.openai.com/api/docs/models/gpt-5.6-sol",
161
+ checkedAt: CHECKED,
162
+ },
163
+ {
164
+ url: "https://openai.com/index/builders-guide-to-gpt-5-6/",
165
+ checkedAt: CHECKED,
166
+ note: "read through search results; direct fetch returned HTTP 403",
167
+ },
168
+ {
169
+ url: "file://~/.codex/models_cache.json",
170
+ checkedAt: CHECKED,
171
+ note: "codex-cli 0.152.1 served list; `codex exec -m gpt-5.6-sol` returned OK",
172
+ },
173
+ ],
174
+ prompt: [
175
+ "Work from the outcome: know what good looks like and the stopping condition, then choose the method yourself.",
176
+ "Carry the task to completion: gather context, plan, implement, verify, and report the evidence.",
177
+ "Run independent reads and checks in parallel.",
178
+ ],
179
+ operator: [
180
+ "Flagship GPT-5.6 tier for complex professional work: architecture, security review, repo-wide debugging.",
181
+ "Keep the system prompt lean: objective, context, hard constraints, approval boundaries, success criteria, required evidence, and output format.",
182
+ "Efforts: none, low, medium (API default), high, xhigh, max; Codex adds ultra, which runs parallel agents. Codex lists low as its default for this model.",
183
+ "1,050,000-token context, 128K max output.",
184
+ ],
185
+ },
186
+ {
187
+ id: "gpt-5.6-terra",
188
+ name: "GPT-5.6 Terra",
189
+ vendor: "OpenAI",
190
+ surfaces: ["codex", "api", "router"],
191
+ aliases: ["openai/gpt-5.6-terra"],
192
+ defaultEffort: "medium",
193
+ sources: [
194
+ {
195
+ url: "https://developers.openai.com/api/docs/models/gpt-5.6-terra",
196
+ checkedAt: CHECKED,
197
+ },
198
+ {
199
+ url: "file://~/.codex/models_cache.json",
200
+ checkedAt: CHECKED,
201
+ note: "codex-cli 0.152.1 served list; `codex exec -m gpt-5.6-terra` returned OK",
202
+ },
203
+ ],
204
+ prompt: [
205
+ "Work from the outcome and the stopping condition; choose the method yourself and verify before you report.",
206
+ ],
207
+ operator: [
208
+ "Balanced GPT-5.6 tier for everyday professional coding.",
209
+ "Efforts: none, low, medium (default), high, xhigh, max; Codex adds ultra.",
210
+ "1,050,000-token context, 128K max output.",
211
+ ],
212
+ },
213
+ {
214
+ id: "gpt-5.6-luna",
215
+ name: "GPT-5.6 Luna",
216
+ vendor: "OpenAI",
217
+ surfaces: ["codex", "api", "router"],
218
+ aliases: ["openai/gpt-5.6-luna"],
219
+ defaultEffort: "medium",
220
+ sources: [
221
+ {
222
+ url: "https://developers.openai.com/api/docs/models/gpt-5.6-luna",
223
+ checkedAt: CHECKED,
224
+ },
225
+ {
226
+ url: "file://~/.codex/models_cache.json",
227
+ checkedAt: CHECKED,
228
+ note: "codex-cli 0.152.1 served list; `codex exec -m gpt-5.6-luna` returned OK",
229
+ },
230
+ ],
231
+ prompt: [
232
+ "Follow the stated format exactly and finish each item before moving to the next.",
233
+ ],
234
+ operator: [
235
+ "GPT-5.6 tier for cost-sensitive, high-volume work: summarizing, labeling, extraction, scaffolds.",
236
+ "Efforts: none, low, medium (default), high, xhigh, max. Raise effort for harder items.",
237
+ "1,050,000-token context, 128K max output.",
238
+ ],
239
+ },
240
+ {
241
+ id: "deepseek-v4.1-flash",
242
+ name: "DeepSeek V4.1 Flash",
243
+ vendor: "DeepSeek",
244
+ surfaces: ["api", "router"],
245
+ aliases: ["deepseek-flash", "deepseek/deepseek-v4.1-flash"],
246
+ sources: [
247
+ {
248
+ url: "https://api-docs.deepseek.com/news/news260910/",
249
+ checkedAt: CHECKED,
250
+ },
251
+ {
252
+ url: "https://api-docs.deepseek.com/quick_start/pricing",
253
+ checkedAt: CHECKED,
254
+ },
255
+ {
256
+ url: "https://router.tangle.tools/v1/chat/completions",
257
+ checkedAt: CHECKED,
258
+ note: "deepseek/deepseek-v4.1-flash returned HTTP 200 and served that id",
259
+ },
260
+ ],
261
+ prompt: [
262
+ "State the goal and the finished result up front, and use the tools you are given to check your work.",
263
+ ],
264
+ operator: [
265
+ "Vendor API id deepseek-flash (released 2026-09-10); on the Tangle router, deepseek/deepseek-v4.1-flash.",
266
+ "1M context, 384K max output; thinking mode is the default and non-thinking is available. Native vision.",
267
+ "OpenCode supports it as an official partner harness.",
268
+ ],
269
+ },
270
+ {
271
+ id: "glm-5.3",
272
+ name: "GLM-5.3",
273
+ vendor: "Z.ai",
274
+ surfaces: ["api", "router"],
275
+ aliases: ["z-ai/glm-5.3", "zai-coding-plan/glm-5.3"],
276
+ defaultEffort: "ultracode",
277
+ sources: [
278
+ { url: "https://docs.z.ai/guides/llm/glm-5.3", checkedAt: CHECKED },
279
+ {
280
+ url: "https://router.tangle.tools/v1/chat/completions",
281
+ checkedAt: CHECKED,
282
+ note: "glm-5.3 returned HTTP 200, served as z-ai/glm-5.3",
283
+ },
284
+ ],
285
+ prompt: [
286
+ "Work the task through to a verified result, using the tools to run and check each change.",
287
+ ],
288
+ operator: [
289
+ "Model id glm-5.3; text only; 1M context, 128K max output. Built for long-horizon software engineering.",
290
+ "Reasoning is always on: thinking.type enabled with reasoning_effort low, high, or max (default). Use max for coding.",
291
+ ],
292
+ },
293
+ {
294
+ id: "kimi-k3",
295
+ name: "Kimi K3",
296
+ vendor: "Moonshot AI",
297
+ surfaces: ["api", "router"],
298
+ aliases: ["moonshotai/kimi-k3", "kimi-code/k3"],
299
+ defaultEffort: "ultracode",
300
+ sources: [
301
+ {
302
+ url: "https://platform.kimi.ai/docs/guide/kimi-k3-quickstart",
303
+ checkedAt: CHECKED,
304
+ },
305
+ {
306
+ url: "https://router.tangle.tools/v1/chat/completions",
307
+ checkedAt: CHECKED,
308
+ note: "kimi-k3 returned HTTP 200, served as moonshotai/kimi-k3",
309
+ },
310
+ ],
311
+ prompt: [
312
+ "Navigate the repository, run the code, and iterate against tests, logs, and runtime output until the result holds.",
313
+ ],
314
+ operator: [
315
+ "Model id kimi-k3; 1M context; native vision. For long-horizon coding, knowledge work, and reasoning.",
316
+ "Thinking is always on: reasoning_effort low, high, or max (default).",
317
+ "Sampling is fixed (temperature 1.0, top_p 0.95); omit sampling parameters.",
318
+ "Return the complete assistant message unchanged in multi-turn and tool-call histories.",
319
+ ],
320
+ },
321
+ ];
@@ -0,0 +1,12 @@
1
+ import type { ProfileKbDiscrepancy, ProfileKbLearning } from "./types.js";
2
+ /**
3
+ * Lessons this platform measured itself. A lesson enters only after an
4
+ * agent-eval check reproduced it strongly; none has met that bar yet, so the
5
+ * list is empty rather than filled with single-run observations.
6
+ */
7
+ export declare const profileKbLearnings: readonly ProfileKbLearning[];
8
+ /**
9
+ * Names the platform asked for that vendor sources state differently, as read
10
+ * on 2026-09-22. Recorded instead of guessed.
11
+ */
12
+ export declare const profileKbDiscrepancies: readonly ProfileKbDiscrepancy[];
@@ -0,0 +1,62 @@
1
+ const CHECKED = "2026-09-22";
2
+ /**
3
+ * Lessons this platform measured itself. A lesson enters only after an
4
+ * agent-eval check reproduced it strongly; none has met that bar yet, so the
5
+ * list is empty rather than filled with single-run observations.
6
+ */
7
+ export const profileKbLearnings = [];
8
+ /**
9
+ * Names the platform asked for that vendor sources state differently, as read
10
+ * on 2026-09-22. Recorded instead of guessed.
11
+ */
12
+ export const profileKbDiscrepancies = [
13
+ {
14
+ subject: "OpenAI Codex models",
15
+ requested: "gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna as the current Codex models",
16
+ observed: "OpenAI's Codex model page lists GPT-6 Astra, GPT-6 Sol, and GPT-6 Luna as the current recommended models. " +
17
+ "On this box, codex-cli 0.152.1 on a ChatGPT account serves gpt-5.6-sol, gpt-5.6-terra, and gpt-5.6-luna (each returned OK) " +
18
+ "and labels them 'Older'; gpt-6-sol and gpt-6-luna return 'not supported when using Codex with a ChatGPT account', " +
19
+ "and gpt-6-astra returns 'requires a newer version of Codex'. The knowledge base keeps the gpt-5.6 tiers because they are what this box can run.",
20
+ sources: [
21
+ { url: "https://learn.chatgpt.com/docs/models", checkedAt: CHECKED },
22
+ {
23
+ url: "cli:codex exec -m <model> 'Reply with exactly: OK'",
24
+ checkedAt: CHECKED,
25
+ },
26
+ ],
27
+ },
28
+ {
29
+ subject: "DeepSeek V4.1 Pro",
30
+ requested: "DeepSeek V4.1 Pro",
31
+ observed: "DeepSeek has released V4.1 Flash only (2026-09-10). Its changelog says the V4 Pro API continues, its pricing page maps " +
32
+ "deepseek-v4-pro to DeepSeek-V4-Pro-0813, and its V4.1 Flash announcement says deepseek-v4-pro routes to V4.1 Flash from 2026-09-14. " +
33
+ "On the Tangle router, deepseek-v4-pro returned HTTP 503 (provider quota exhausted). No V4.1 Pro entry exists until DeepSeek ships it.",
34
+ sources: [
35
+ { url: "https://api-docs.deepseek.com/updates/", checkedAt: CHECKED },
36
+ { url: "https://api-docs.deepseek.com/quick_start/pricing", checkedAt: CHECKED },
37
+ { url: "https://api-docs.deepseek.com/news/news260910/", checkedAt: CHECKED },
38
+ ],
39
+ },
40
+ {
41
+ subject: "DeepSeek V4.1 Flash router id",
42
+ requested: "deepseek-flash (the vendor id)",
43
+ observed: "On the Tangle router, deepseek-flash returned HTTP 503 (provider_pricing_unavailable); deepseek/deepseek-v4.1-flash returned HTTP 200.",
44
+ sources: [
45
+ {
46
+ url: "https://router.tangle.tools/v1/chat/completions",
47
+ checkedAt: CHECKED,
48
+ },
49
+ ],
50
+ },
51
+ {
52
+ subject: "GPT-6 Pro",
53
+ requested: "GPT-6 Pro in ChatGPT",
54
+ observed: "OpenAI's help center names GPT-6 Pro as a ChatGPT mode powered by GPT-6 Astra; it has no API model id.",
55
+ sources: [
56
+ {
57
+ url: "https://help.openai.com/en/articles/20001354-gpt-56-and-gpt-6-pro-in-chatgpt",
58
+ checkedAt: CHECKED,
59
+ },
60
+ ],
61
+ },
62
+ ];
@@ -0,0 +1,76 @@
1
+ import type { HarnessType } from "../harness.js";
2
+ import type { ReasoningEffort } from "../agent-profile.js";
3
+ /** A vendor or measured source, with the date someone read or ran it. */
4
+ export interface ProfileKbSource {
5
+ url: string;
6
+ /** ISO date (YYYY-MM-DD) the source was read or the command was run. */
7
+ checkedAt: string;
8
+ /** What the source is, when the URL alone does not say. */
9
+ note?: string;
10
+ }
11
+ /**
12
+ * How to get the best from one harness.
13
+ *
14
+ * `prompt` lines are addressed to the agent running inside the harness and
15
+ * are composed into its profile. `operator` lines are for whoever launches
16
+ * the harness; they are never sent to a model.
17
+ */
18
+ export interface ProfileKbHarness {
19
+ id: HarnessType;
20
+ name: string;
21
+ /** Installed version the guidance was checked against. */
22
+ version: string;
23
+ sources: ProfileKbSource[];
24
+ prompt: string[];
25
+ operator: string[];
26
+ }
27
+ /** Where a model is reached. A model id means different things on each surface. */
28
+ export type ProfileKbSurface = "api" | "codex" | "chatgpt" | "router";
29
+ /**
30
+ * How to get the best from one model.
31
+ *
32
+ * Vendor guidance only, each entry citing its source and date. The guidance is
33
+ * positive and specific to this model; it never ranks the model against
34
+ * another.
35
+ */
36
+ export interface ProfileKbModel {
37
+ /** Canonical vendor id. */
38
+ id: string;
39
+ name: string;
40
+ vendor: string;
41
+ surfaces: ProfileKbSurface[];
42
+ /** Other spellings that resolve to this model: router ids, harness aliases. */
43
+ aliases: string[];
44
+ /** Vendor default reasoning effort, mapped onto the portable scale. */
45
+ defaultEffort?: ReasoningEffort;
46
+ sources: ProfileKbSource[];
47
+ prompt: string[];
48
+ operator: string[];
49
+ }
50
+ /**
51
+ * A lesson this platform learned itself. It enters the knowledge base only
52
+ * after an agent-eval check reproduced it, and it stays scoped to the
53
+ * harness or model it was measured on.
54
+ */
55
+ export interface ProfileKbLearning {
56
+ id: string;
57
+ appliesTo: {
58
+ harness?: HarnessType;
59
+ model?: string;
60
+ };
61
+ text: string;
62
+ evidence: {
63
+ /** The agent-eval check that reproduced the lesson. */
64
+ check: string;
65
+ /** Independent reproductions that passed. */
66
+ reproductions: number;
67
+ source: ProfileKbSource;
68
+ };
69
+ }
70
+ /** A name the platform asked for that a vendor source does not confirm as stated. */
71
+ export interface ProfileKbDiscrepancy {
72
+ subject: string;
73
+ requested: string;
74
+ observed: string;
75
+ sources: ProfileKbSource[];
76
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-interface",
3
- "version": "2.10.0",
3
+ "version": "2.11.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",
@@ -66,6 +66,11 @@
66
66
  "import": "./dist/interaction.js",
67
67
  "types": "./dist/interaction.d.ts",
68
68
  "default": "./dist/interaction.js"
69
+ },
70
+ "./profile-kb": {
71
+ "import": "./dist/profile-kb/index.js",
72
+ "types": "./dist/profile-kb/index.d.ts",
73
+ "default": "./dist/profile-kb/index.js"
69
74
  }
70
75
  },
71
76
  "repository": {