Agent Construction
The SDK exposes two construction entry points, and choosing the right one is the first important API decision.
Choose the builder
| Builder | Use it when... |
|---|---|
createAgent(...) | you want the minimal loop and will own prompts, planning, and context behavior yourself |
createSmartAgent(...) | you are building an autonomous or semi-autonomous agent that needs profiles, planning, summarization, memory, and better operational defaults |
createSmartAgent(...)
function createSmartAgent<TOutput = unknown>(options: SmartAgentOptions): SmartAgentInstance<TOutput>Key option groups
model: the model adapter used by the runtimetools: local or adapted toolsruntimeProfile: built-in preset orcustomplanning: explicit multi-step workflow controlsummarization,context,toolResponses: context pressure handlingmemory: fact read/write policydelegation: child-agent behaviorwatchdog: token drift and over-tooling responsetracing: execution telemetryoutputSchema: deterministic structured output
Example
import { createSmartAgent, createTool, fromLangchainModel } from "@cognipeer/agent-sdk";
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
const lookup = createTool({
name: "lookup_project",
description: "Return project facts",
schema: z.object({ code: z.string() }),
func: async ({ code }) => ({ code, owner: "Ada Lovelace", risk: "low" }),
});
const agent = createSmartAgent({
name: "ProjectAssistant",
model: fromLangchainModel(new ChatOpenAI({ model: "gpt-4o-mini" })),
tools: [lookup],
runtimeProfile: "balanced",
planning: { mode: "todo" },
limits: { maxToolCalls: 8, maxContextTokens: 12000 },
tracing: { enabled: true },
});Why smart runtime users care
createSmartAgent(...) is the entry point you usually want for autonomous agents because it manages:
- adaptive planning
- model-facing context shaping
- summarization and archival
- memory fact sync
- canonical
state.planupdates - watchdog telemetry such as token drift and context rot
createAgent(...)
function createAgent<TOutput = unknown>(options: AgentOptions): AgentInstance<TOutput>Use this when you want the smallest deterministic loop and do not want smart runtime behavior to wrap the model call.
const agent = createAgent({
model,
tools: [lookup],
limits: { maxToolCalls: 4 },
});createAgent(...) still supports tools, approvals, handoffs, tracing, and structured output. It simply leaves planning and context strategy up to you.
Shared instance methods
Both builders expose more than invoke(...):
invoke(state, config?)snapshot(state, options?)resume(snapshot, options?)resolveToolApproval(state, resolution)asTool(options?)asHandoff(options?)
These methods matter if your agent is long-running, approval-gated, resumable, or composed into a bigger agent system.
invoke(...)
agent.invoke(state, config?)Important InvokeConfig hooks:
onEvent(event)for tool, plan, trace, and handoff visibilityonStateChange(state)for pause and checkpoint workflowscheckpointReasonto annotate why a snapshot was taken
Result shape
type AgentInvokeResult<TOutput = unknown> = {
content: string;
output?: TOutput;
messages: Message[];
state?: SmartState;
metadata?: { usage?: any };
}State surfaces worth integrating
state.messagesstate.toolHistorystate.toolHistoryArchivedstate.planstate.planVersionstate.summaryRecordsstate.memoryFactsstate.watchdog
If you are using the smart runtime, prefer state.plan over any event-only or legacy todo mental model.