feat(deepagents): implement harness profiles (#526)
### Summary
Introduces harness profiles which is a way to declaratively control how
agents behave at runtime without changing which model is used. A profile
can override the system prompt, hide tools, add or remove middleware,
and configure the general-purpose subagent. Profiles are registered by
provider or model key ("anthropic", "openai:gpt-5.4") and looked up
automatically when `createDeepAgent` is called.
The system ships with built-in profiles for Anthropic Opus 4.7, Sonnet
4.6, Haiku 4.5, and OpenAI Codex that include vendor-recommended
prompting guidance. Users can register their own profiles on top and
registrations merge additively so provider-wide defaults compose with
model-specific overrides.
Profiles are plain frozen objects with Zod schemas for parsing from
JSON/YAML config files, including prototype-pollution protection for
untrusted input.
### Tests
Unit tests cover key validation, profile construction and freezing,
serialization round-trips, poison-key rejection, merge semantics across
all field types, registry lookup with provider fallback, and prompt
overlay behavior. Built-in profiles are tested for correct registration
and expected content.
Also verified end-to-end via a standalone script against LangSmith and
confirmed the custom suffix appears in the system prompt and excluded
tools are absent from the model call.
### Usage Example
```ts
import { HumanMessage } from "@langchain/core/messages";
import { createDeepAgent, registerHarnessProfile } from "deepagents";
registerHarnessProfile("anthropic:claude-sonnet-4-6", {
systemPromptSuffix: "Always respond in exactly one sentence.",
excludedTools: ["grep"],
generalPurposeSubagent: {
description: "A customized GP subagent via harness profile.",
},
});
const agent = createDeepAgent({
model: "anthropic:claude-sonnet-4-6",
});
const result = await agent.invoke({
messages: [new HumanMessage("What is the capital of France?")],
});
const lastMessage = result.messages[result.messages.length - 1];
console.log("Response:", lastMessage.content);
``` C
Colin Francis committed
7c33a8695f2e16217779bef5c6fca28230f18815
Parent: c231aed
Committed by GitHub <noreply@github.com>
on 5/11/2026, 9:57:29 PM