@robota-sdk/agent-core
v3.0.0-beta.79
Published
Complete AI agent implementation with unified core and tools functionality - conversation management, plugin system, and advanced agent features
Maintainers
Readme
Agent Core
The foundation layer of the Robota SDK. Provides the Robota agent class, abstract base classes for providers/tools/plugins, the permission system, hook system, event services, and error hierarchy.
Installation
npm install @robota-sdk/agent-coreQuick Start
import { Robota } from '@robota-sdk/agent-core';
import { AnthropicProvider } from '@robota-sdk/agent-provider/anthropic';
const provider = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY });
const agent = new Robota({
name: 'MyAgent',
aiProviders: [provider],
defaultModel: {
provider: 'anthropic',
model: 'claude-sonnet-4-6',
},
systemMessage: 'You are a helpful assistant.',
});
const response = await agent.run('Hello, world!');
console.log(response);Key Features
- Robota class: AI agent with conversation history, tool execution, and plugin support
- ConversationStore: Append-only conversation history with streaming buffer (
beginAssistant/appendStreaming/commitAssistant) - IBaseMessage: Every message has a unique
id(UUID) andstate('complete'|'interrupted') - Multi-provider: Register multiple providers, switch dynamically with
setModel() - Provider capabilities: Provider-neutral capability reports distinguish local tools from provider-native hosted web search/fetch
- AbstractAIProvider.streamWithAbort(): Standard streaming wrapper for all providers — handles AbortSignal, returns partial content on abort
- Permission system: Deterministic 3-step policy evaluation (
evaluatePermission) - Hook system: Shell command-based lifecycle hooks (
runHooks) - Plugin system:
AbstractPluginbase class with lifecycle hooks (beforeRun, afterRun, onError, etc.) - Event services: Unified event emission with owner path tracking
- Error hierarchy: Typed errors extending
RobotaError(ProviderError, RateLimitError, etc.) - Model definitions: Central
CLAUDE_MODELSregistry with context windows, output limits, and human-readable names - callProviderWithCache: Accepts
Partial<IChatOptions>overrides for per-call configuration - AbortSignal propagation: Signal flows through the entire execution chain (Session -> Robota -> Provider)
- Execution boundary events:
Robota.run()can emit provider/tool provenance events throughonExecutionEvent - Type safety: Strict TypeScript, zero
anyin production code
Robota API
import { Robota } from '@robota-sdk/agent-core';
import type { IAgentConfig } from '@robota-sdk/agent-core';
declare const config: IAgentConfig;
const agent = new Robota(config);
// Send a message (executes tool calls automatically)
const response = await agent.run('Hello');
// Conversation history
const history = agent.getHistory(); // TUniversalMessage[]
agent.clearHistory();
// Switch provider/model mid-conversation
agent.setModel({ provider: 'openai', model: 'gpt-4o' });Structured Output
run(input, { output }) returns a schema-validated object instead of a string. Zod schemas give a
typed result; the schema is forwarded to the provider's native structured-output surface where one
exists, and the response is always validated core-side with a bounded retry on violation
(outputRetries, default 2). Exhausted retries throw StructuredOutputError.
import { z } from 'zod';
import { Robota } from '@robota-sdk/agent-core';
import type { IAgentConfig } from '@robota-sdk/agent-core';
declare const config: IAgentConfig;
const agent = new Robota(config);
const reportSchema = z.object({
title: z.string(),
score: z.number(),
summary: z.string(),
});
// Typed result: { title: string; score: number; summary: string }
const report = await agent.run('Summarize the meeting as a report.', {
output: reportSchema,
});
// Streaming variant: deltas stream as usual; the validated object is the
// generator's return value (the final { done: true, value } iterator result).
const stream = agent.runStream('Summarize again.', { output: reportSchema });
const iterator = stream[Symbol.asyncIterator]();
let next = await iterator.next();
while (!next.done) {
process.stdout.write(next.value);
next = await iterator.next();
}
const streamedReport = next.value;
console.log(streamedReport.title);A raw JSON-schema wrapper is also accepted: { output: { jsonSchema: { type: 'object', properties: { answer: { type: 'string' } }, required: ['answer'] } } }.
Model Options per Run
run/runStream accept run-scoped model options that win over defaultModel.*:
maxTokens, temperature, and toolChoice. toolChoice directs tool invocation —
'auto' (model decides), 'none' (suppress tool calls), 'required' (must call some
tool), or { tool: name } (must call the named tool). A named tool missing from the run's
tool list throws immediately; nothing is silently ignored. Forcing directives apply to the
run's first model call only — rounds after tool results revert to 'auto' so the model can
consume the results and finish.
import { Robota } from '@robota-sdk/agent-core';
import type { IAgentConfig } from '@robota-sdk/agent-core';
declare const config: IAgentConfig;
const agent = new Robota(config);
// Force the model to answer via the router tool (decision-agent pattern)
const decision = await agent.run('Route this request.', {
toolChoice: { tool: 'route-request' },
allowToolOnlyCompletion: true,
});
// Suppress tools for a plain-text turn, capped at 100 output tokens
const summary = await agent.run('Summarize the discussion.', {
toolChoice: 'none',
maxTokens: 100,
});
console.log(decision, summary);The same directive can be set agent-wide via defaultModel.toolChoice.
Execution Boundary Events
run() accepts onExecutionEvent in run options. The execution loop emits provider-neutral events that higher layers can persist as append-only session provenance:
provider_requestprovider_native_raw_payloadprovider_stream_raw_deltaprovider_response_rawprovider_response_normalizedassistant_message_committedtool_batch_startedtool_execution_requesttool_execution_resulttool_message_committedhistory_mutation
Provider-specific SDK payload capture remains provider-owned. Providers may call IChatOptions.onProviderNativeRawPayload with exact SDK request, response, or stream event objects; Robota forwards those callbacks as provider-neutral provider_native_raw_payload execution events without importing concrete provider SDK types. provider_response_raw.responseKind remains provider-normalized-message, which keeps common replay validation provider-neutral.
IAgentConfig
| Field | Type | Description |
| ----------------------- | -------------------------- | ------------------------------ |
| name | string | Agent name |
| aiProviders | IAIProvider[] | One or more provider instances |
| defaultModel.provider | string | Provider name |
| defaultModel.model | string | Model identifier |
| systemMessage | string? | System prompt (top-level) |
| tools | IToolWithEventService[]? | Tools the agent can call |
| plugins | IPluginContract[]? | Plugins for lifecycle hooks |
Architecture
agent-core (this package — zero workspace dependencies)
↑
agent-session ← Session lifecycle
agent-tools ← Tool implementations
agent-provider ← AI provider implementations (consolidated, multi-vendor sub-paths)
agent-plugin ← Plugin implementations (8 plugins, consolidated)
↑
agent-framework ← Assembly layer
↑
agent-cli ← Terminal UIPublic API Surface
| Category | Exports |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Core | Robota, ConversationStore, AbstractAgent, AbstractAIProvider (+ streamWithAbort), AbstractPlugin, AbstractTool, AbstractExecutor, LocalExecutor, getProviderCapabilities, assertProviderNativeWebToolsAvailable |
| Permissions | evaluatePermission, MODE_POLICY, TRUST_TO_MODE, UNKNOWN_TOOL_FALLBACK, TPermissionMode, TTrustLevel, TPermissionDecision, TToolArgs, IPermissionLists, TKnownToolName |
| Hooks | runHooks, CommandExecutor, HttpExecutor, IHookTypeExecutor, THookEvent, THooksConfig, IHookGroup, IHookDefinition, IHookInput, IHookResult |
| Events | EventEmitterPlugin, IEventService, IOwnerPathSegment |
| Models | CLAUDE_MODELS, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_OUTPUT, getModelContextWindow(), getModelMaxOutput(), getModelName(), formatTokenCount(), IModelDefinition |
| Context | estimateContextTokensFromMessages(), estimateSerializedContextTokens(), readTokenUsageFromMessage(), IContextTokenEstimate, IMessageTokenUsage, IContextWindowState, IContextTokenUsage |
| Types | TUniversalMessage, IBaseMessage (id, state), TMessageState, IAgentConfig, IAIProvider, IProviderCapabilities, IProviderNativeWebToolRequest, IToolSchema, TTextDeltaCallback |
| Errors | RobotaError, ProviderError, RateLimitError, AuthenticationError, ToolExecutionError, etc. |
| Managers | AgentFactory, AgentTemplates, ConversationHistory, EventHistoryModule |
What Moved Out in v3
| What | Moved to |
| --------------------------------------------- | ---------------------------- |
| FunctionTool, ToolRegistry, OpenAPITool | @robota-sdk/agent-tools |
| MCPTool, RelayMcpTool | @robota-sdk/agent-tool-mcp |
| 8 plugins (logging, usage, performance, etc.) | @robota-sdk/agent-plugin |
License
Robota is dual-licensed under the GNU AGPL-3.0 or a commercial license. See LICENSING.md.
