Skip to content

Agent Core Specification

Scope

  • Owns the core Robota agent runtime, tool integration, conversation execution, and plugin-facing agent behavior.
  • Defines the canonical agent orchestration surface used by provider and higher-level packages.
  • Provides abstract base classes that provider packages and extensions must implement.

Boundaries

  • Keeps provider-specific transport behavior in provider packages (@robota-sdk/agent-provider-openai, @robota-sdk/agent-provider-anthropic, @robota-sdk/agent-provider-google).
  • Keeps package-specific domain contracts owned once and reused through public surfaces.
  • Does not own workflow visualization, DAG orchestration, or session persistence (those belong to dag-*, @robota-sdk/agent-sessions).

Architecture Overview

Layer Structure

Robota (Facade)
  ├── ExecutionService (Orchestrator)
  │     ├── AI Provider call (via AIProviders manager)
  │     └── Tool execution (via ToolExecutionService)
  ├── Manager Layer
  │     ├── AIProviders        — provider registration and selection
  │     ├── Tools              — tool registry and schema lookup
  │     ├── AgentFactory       — agent creation and lifecycle
  │     ├── ConversationHistory — session and message storage
  │     └── ModuleRegistry     — dynamic module loading
  ├── Service Layer
  │     ├── ExecutionService        — message handling, LLM calls, response assembly
  │     ├── ToolExecutionService    — schema validation, tool lookup, batch execution
  │     └── EventService            — unified event emission with ownerPath binding
  ├── Permission Layer
  │     ├── permission-gate.ts      — evaluatePermission(): 3-step deterministic policy
  │     ├── permission-mode.ts      — MODE_POLICY matrix, UNKNOWN_TOOL_FALLBACK
  │     └── types.ts                — TPermissionMode, TTrustLevel, TPermissionDecision
  ├── Hook Layer
  │     ├── hook-runner.ts          — runHooks(): pluggable hook execution engine (strategy pattern)
  │     ├── command-executor.ts     — CommandExecutor: shell command hook execution
  │     ├── http-executor.ts        — HttpExecutor: HTTP request hook execution
  │     └── types.ts                — THookEvent (8 events), IHookDefinition (discriminated union), IHookTypeExecutor
  └── Plugin Layer (1 built-in + 8 external @robota-sdk/agent-plugin-* packages)
        ├── EventEmitterPlugin           (built-in — event coordination)
        └── External plugins (per @robota-sdk/agent-plugin-*):
              conversation-history, logging, usage, performance,
              execution-analytics, error-handling, limits, webhook

Design Patterns

  • Facade: Robota is the single entry point, hiding manager/service/plugin complexity.
  • Template Method: AbstractAgent defines lifecycle hooks (beforeRun, afterRun, onError).
  • Strategy: Event services, storage strategies, error handling strategies are interchangeable.
  • Registry: ToolRegistry and ModuleRegistry for central resource management.
  • Null Object: SilentLogger and DefaultEventService provide safe no-op defaults.
  • Factory: AgentFactory for agent creation with lifecycle hooks.
  • Observer: EventEmitterPlugin for pub/sub event coordination.

Dependency Injection

All managers, services, and tools accept dependencies through constructor injection. No global singletons exist. Each Robota instance is completely independent.

Safe defaults use the Null Object pattern:

  • SilentLogger for logging (no side effects)
  • DEFAULT_ABSTRACT_EVENT_SERVICE for events (no-op)

Type Ownership

This package is the single source of truth (SSOT) for the following types:

TypeLocationPurpose
TUniversalMessageinterfaces/messages.tsCanonical message union (User, Assistant, System, Tool)
TUniversalMessageMetadatainterfaces/messages.tsMessage metadata record. Values: string | number | boolean | Date | string[] | number[] | Record<string, number> (includes token usage objects)
TUniversalValueinterfaces/types.tsRecursive value type without any
TMetadatainterfaces/types.tsMetadata record type
IAgentConfiginterfaces/agent.tsAgent configuration contract
IAIProviderinterfaces/provider.tsProvider integration contract
IToolSchemainterfaces/provider.tsTool schema contract
TToolParametersinterfaces/types.tsTool parameter type (re-exported via interfaces/tool.ts)
IEventServiceevent-service/interfaces.tsEvent emission contract
IOwnerPathSegmentevent-service/interfaces.tsExecution path tracking
RobotaErrorutils/errors.tsBase error hierarchy
TTextDeltaCallbackinterfaces/provider.tsStreaming text delta callback (delta: string) => void
TPermissionModepermissions/types.tsPermission modes: plan, default, acceptEdits, bypassPermissions
TTrustLevelpermissions/types.tsFriendly trust aliases: safe, moderate, full
TPermissionDecisionpermissions/types.tsEvaluation outcome: auto, approve, deny
TToolArgspermissions/permission-gate.tsTool arguments record for permission matching
IPermissionListspermissions/permission-gate.tsAllow/deny pattern lists for permission config
TKnownToolNamepermissions/permission-mode.tsKnown tool names in the permission system
THookEventhooks/types.tsHook lifecycle events (7 events): PreToolUse, PostToolUse, PreCompact, PostCompact, SessionStart, Stop, UserPromptSubmit
THooksConfighooks/types.tsComplete hooks configuration: event to hook groups
IHookGrouphooks/types.tsHook group: matcher pattern + hook definitions
IHookDefinitionhooks/types.tsDiscriminated union hook definition (type: command, http, prompt, agent)
IHookTypeExecutorhooks/types.tsStrategy interface for hook type execution
IHookInputhooks/types.tsInput passed to hook commands via stdin
IHookResulthooks/types.tsHook execution result (exitCode, stdout, stderr)
IContextTokenUsagecontext/types.tsToken usage from a single API call (input, output, cache tokens)
IContextWindowStatecontext/types.tsContext window state snapshot (maxTokens, usedTokens, percentage)
IHistoryEntryinterfaces/history.tsRich history entry that wraps a message with category, type, and structured data fields. Fields: id (string), timestamp (Date), category ('chat' | 'event'), type (string), data (varies by category/type)

Provider packages import these types. They must not re-declare them.

Model Definitions (SSOT)

context/models.ts is the single source of truth for Claude model metadata. Source: https://platform.claude.com/docs/en/about-claude/models/overview

ExportKindDescription
IModelDefinitionInterfaceModel metadata: name, id, contextWindow, maxOutput
CLAUDE_MODELSRecordAll known Claude models (4.5+) keyed by API ID
DEFAULT_CONTEXT_WINDOWConstant200,000 tokens fallback
DEFAULT_MAX_OUTPUTConstant16,384 tokens fallback for max output
getModelContextWindow(id)FunctionGet context window size for a model ID
getModelMaxOutput(id)FunctionGet max output tokens for a model ID
getModelName(id)FunctionGet human-readable name (e.g., "Claude Sonnet 4.6")
formatTokenCount(tokens)FunctionFormat tokens as human-readable (e.g., "200K", "1M")

Public API Surface

Core

ExportKindDescription
RobotaclassMain agent facade
AbstractAgentabstract classBase agent lifecycle
AbstractAIProviderabstract classBase for provider implementations
AbstractPluginabstract classBase for plugin extensions
AbstractToolabstract classBase for tool implementations
AbstractExecutorabstract classBase for execution strategies
LocalExecutorclassLocal provider execution

Tools

NOTE: ToolRegistry, FunctionTool, createFunctionTool, createZodFunctionTool, and OpenAPITool have been moved to @robota-sdk/agent-tools. MCPTool and RelayMcpTool have been moved to @robota-sdk/agent-tool-mcp.

Permissions

ExportKindDescription
evaluatePermissionfunction3-step deterministic policy: deny list, allow list, mode
MODE_POLICYconstPermission mode to tool decision matrix
TRUST_TO_MODEconstMaps TTrustLevel to TPermissionMode
UNKNOWN_TOOL_FALLBACKconstFallback decisions for unknown tools per mode
TPermissionModetype'plan' | 'default' | 'acceptEdits' | 'bypassPermissions'
TTrustLeveltype'safe' | 'moderate' | 'full'
TPermissionDecisiontype'auto' | 'approve' | 'deny'
TToolArgstypeTool arguments record for permission matching
IPermissionListstypeAllow/deny pattern lists
TKnownToolNametypeKnown tool names: Bash, Read, Write, Edit, Glob, Grep

Hooks

ExportKindDescription
runHooksfunctionExecute hooks for lifecycle events using pluggable type executors
THookEventtype7 events: PreToolUse, PostToolUse, SessionStart, Stop, PreCompact, PostCompact, UserPromptSubmit
THooksConfigtypeEvent to hook group array mapping
IHookGrouptypeMatcher pattern + hook definitions
IHookDefinitiontypeDiscriminated union: command, http, prompt, agent hook types
IHookTypeExecutorinterfaceStrategy interface for executing a specific hook type
CommandExecutorclassBuilt-in executor for command type hooks (shell execution)
HttpExecutorclassBuilt-in executor for http type hooks (HTTP request)
IHookInputtypeJSON input passed to hooks via stdin
IHookResulttypeHook result: exitCode (0=allow, 2=block), stdout, stderr

Streaming

ExportKindDescription
TTextDeltaCallbacktype(delta: string) => void — streaming text callback

This callback is declared in IChatOptions.onTextDelta and used by providers to emit text chunks during streaming responses.

Context Window Tracking

ExportKindDescription
IContextTokenUsageinterfaceToken usage from a single API call (inputTokens, outputTokens, cache)
IContextWindowStateinterfaceContext window state snapshot (maxTokens, usedTokens, usedPercentage)

These types are consumed by @robota-sdk/agent-sessions to track cumulative token usage and context window state across conversation turns.

History Entry Helpers

ExportKindDescription
IHistoryEntryinterfaceRich history entry: id, timestamp, category ('chat' | 'event'), type, data
isChatEntryfunctionType guard: (entry: IHistoryEntry) => entry is IChatHistoryEntry — narrows to chat category entries
chatEntryToMessagefunctionConverts an IChatHistoryEntry to a TUniversalMessage for API use
messageToHistoryEntryfunctionConverts a TUniversalMessage to an IHistoryEntry with category: 'chat'
getMessagesForAPIfunctionExtracts TUniversalMessage[] from IHistoryEntry[] for provider API calls (filters to chat entries only)

Managers

ExportKindDescription
AgentFactoryclassAgent creation and lifecycle
AgentTemplatesclassTemplate-based agent creation
ConversationHistoryclassHistory management
ConversationStoreclassSession management

Services

ExportKindDescription
EventHistoryModuleclassEvent recording

Note: AbstractEventService, DefaultEventService, StructuredEventService, and ObservableEventService are internal implementation details and are not exported from src/index.ts.

Plugins (1 built-in)

PluginCategoryDescription
EventEmitterPluginevent_processingEvent coordination

8 plugins were extracted to @robota-sdk/agent-plugin-* packages to comply with the agent-core zero-dependency rule. They extend AbstractPlugin (defined here) and are wired by the consuming layer.

Plugin Contract

Plugins extend AbstractPlugin and implement lifecycle hooks:

HookTimingPurpose
beforeRunBefore LLM callInput transformation, validation
afterRunAfter LLM responseOutput processing, recording
onErrorOn execution errorError handling, recovery
onStreamChunkDuring streamingChunk processing
beforeToolExecutionBefore tool callTool input validation
afterToolExecutionAfter tool resultTool output processing

Plugins declare category (PluginCategory) and priority (PluginPriority) for execution ordering.

Event Architecture

Event Naming

Full event names follow the pattern ownerType.localName:

PrefixOwnerExamples
execution.*ExecutionServiceexecution.start, execution.complete
tool.*ToolExecutionServicetool.execute_start, tool.execute_success
agent.*Robotaagent.completion, agent.created
task.*Task systemtask.started, task.completed
user.*User actionsuser.input

Owner Path Tracking

Each event carries an ownerPath array of IOwnerPathSegment objects that traces the execution hierarchy:

typescript
interface IOwnerPathSegment {
  ownerType: string; // 'agent' | 'tool' | 'execution'
  ownerId: string;
}

Events are bound to their owner via bindWithOwnerPath().

Permission System

The permission module (src/permissions/) provides a deterministic, three-step policy evaluation for tool calls. It is consumed by @robota-sdk/agent-sessions to gate tool execution before delegating to the actual tool.

Evaluation Algorithm (evaluatePermission)

  1. Deny list match -- If any deny pattern matches the tool invocation, return 'deny'.
  2. Allow list match -- If any allow pattern matches, return 'auto' (proceed without prompting).
  3. Mode policy lookup -- Look up the tool in MODE_POLICY[mode]. If found, return the mapped decision. Otherwise, return UNKNOWN_TOOL_FALLBACK[mode].

Permission Modes

ModeRead toolsWrite toolsBash
planautodenydeny
defaultautoapprove (prompt)approve (prompt)
acceptEditsautoautoapprove (prompt)
bypassPermissionsautoautoauto

Pattern Syntax

Patterns follow the format ToolName(argGlob):

  • Bash(pnpm *) -- Bash tool whose command starts with "pnpm "
  • Read(/src/**) -- Read tool whose filePath is under /src/
  • Write(*) -- Write tool with any argument
  • ToolName -- Match any invocation of that tool (no argument constraint)

Hook System

The hook module (src/hooks/) provides a pluggable lifecycle hook mechanism. Hooks support multiple execution types (command, http, prompt, agent) via the strategy pattern. Command hooks receive JSON input on stdin and communicate results via exit codes.

Hook Events

EventTimingPurpose
PreToolUseBefore tool executionValidation, blocking, transformation
PostToolUseAfter tool executionLogging, auditing, notification
SessionStartSession initializationSetup, environment checks
StopSession terminationCleanup, reporting
PreCompactBefore context compactionValidation, logging (trigger: auto/manual)
PostCompactAfter context compactionLogging, notification (includes compact_summary)
UserPromptSubmitAfter user submits promptPre-processing, validation, prompt rewriting

Hook Definition Types (Discriminated Union)

IHookDefinition is a discriminated union on the type field:

TypeFieldsDescription
commandcommand: stringShell command execution (stdin JSON, exit codes)
httpurl: string, method?, headers?HTTP request to an external endpoint
promptprompt: stringLLM prompt injection into session context
agentagent: string, config?Delegate to a sub-agent for processing

Hook Type Executors (Strategy Pattern)

IHookTypeExecutor defines the strategy interface for executing a specific hook type:

typescript
interface IHookTypeExecutor {
  readonly type: string;
  execute(hook: IHookDefinition, input: IHookInput): Promise<IHookResult>;
}

runHooks accepts an optional executors map to register additional hook type executors beyond the built-in ones. This enables higher-level packages to add prompt and agent executors without modifying agent-core.

Built-in executors (agent-core):

ExecutorHook TypeBehavior
CommandExecutorcommandSpawns shell process, passes JSON via stdin, reads exit code
HttpExecutorhttpSends HTTP request, maps response status to exit code

Extended executors (agent-sdk):

ExecutorHook TypeBehavior
PromptExecutorpromptInjects prompt text into session context
AgentExecutoragentDelegates to a sub-agent session for complex processing

Exit Code Protocol

CodeMeaning
0Allow / proceed
2Block / deny (stderr = reason)
otherProceed with warning

Hook Configuration

Hooks are configured as a THooksConfig object mapping events to arrays of IHookGroup entries. Each group has a matcher regex pattern (empty = match all) and an array of IHookDefinition entries. Hooks have a 10-second timeout.

Abort Execution Support

The execution loop supports cooperative cancellation via the standard AbortSignal API. An AbortSignal can be threaded through the entire execution pipeline to allow callers to cancel in-progress runs.

Interface Changes

InterfaceFieldDescription
IRunOptionssignal?: AbortSignalAllows callers to cancel execution of Robota.run()
IChatOptionssignal?: AbortSignalPassed to provider chat() / chatStream() for cancelling calls
IExecutionContextsignal?: AbortSignalThreaded through the execution context for round-level checks
IExecutionResultinterrupted?: booleanIndicates the execution was aborted before natural completion
IToolExecutionBatchContextsignal?: AbortSignalAllows skipping queued tool executions when abort is signalled

Signal Propagation

AbortSignal flows through: Session -> robota.run() -> ExecutionService -> callProviderWithCache -> provider.chat() -> streamWithAbort.

  • ExecutionService: Checks signal.aborted at round loop boundaries. If aborted, the loop exits early and the result includes interrupted: true.
  • callProviderWithCache: Accepts signal and passes it to the provider's chat() call, enabling mid-request cancellation.
  • executeAndRecordToolCalls: Passes signal to the tool batch context so queued tools are skipped once abort is triggered.
  • streamWithAbort: Checks signal.aborted after each yielded event, breaking out of the stream iteration loop.
  • AbortError handling: AbortError exceptions thrown by the fetch layer are caught by the execution loop and treated as a clean interruption (not an error).

Partial Content Preservation on Abort

When abort occurs during provider streaming, the provider uses streamWithAbort which breaks out of the iteration loop on signal.aborted. The provider then returns partial content collected so far with stopReason: 'aborted'. executeRound commits this partial response via commitAssistant('interrupted') through the standard single commit path. The execution loop then exits via the signal.aborted check in ExecutionService. robota.run() always returns normally on abort — it does not throw.

This ensures:

  • The partial response is saved in conversation history for the next turn
  • The model can see what it started saying before interruption
  • Tool results from completed tools in earlier rounds are preserved

If the partial response includes tool_use blocks (abort during tool call streaming), the tool execution step runs but skips queued tools via signal.aborted check in IToolExecutionBatchContext. Completed tools have normal results; skipped tools have "Execution interrupted by user" error results. Both are recorded in history.

Conversation History Principles

  • Append-only: Messages are only added, never edited or deleted.
  • Read-only: Consumers read history but do not mutate existing messages.
  • Always committed: beginAssistant() + commitAssistant() guarantees an assistant message is always appended, even on abort with empty content.
  • No fallback: If a message should be in history, it IS in history. No fallback to alternative data sources.

Message Model

IBaseMessage is the foundation for all message types in the conversation history.

FieldTypeRequiredDescription
idstringYesUUID identifier, auto-generated via randomUUID()
stateTMessageStateYes'complete' | 'interrupted'
rolestringYesMessage role (user, assistant, system, tool)

State rules:

  • Non-assistant messages (user, system, tool) always have state: 'complete'.
  • Only assistant messages may have state: 'interrupted', indicating the response was aborted by the user before natural completion.

Message Factories

All message factory functions auto-generate id via randomUUID() and set state: 'complete' by default.

FactoryRoleNotes
createUserMessageuserAlways state: 'complete'
createAssistantMessageassistantAccepts optional state parameter (default: complete)
createSystemMessagesystemAlways state: 'complete'
createToolMessagetoolAlways state: 'complete'

ConversationStore Streaming State

ConversationStore (renamed from ConversationSession) manages pending assistant state during streaming:

MethodDescription
beginAssistant()Initializes pending state before provider call. Guarantees commitAssistant has data.
appendStreaming(delta)Accumulates streaming text into pending state
appendToolCall(toolCall)Adds tool call to pending state (deduplicates by id)
commitAssistant(state, metadata?)Commits pending to history. Text is ALWAYS preserved. History is append-only.
discardPending()Clears pending without saving
hasPendingAssistant()Checks if streaming is in progress
getPendingContent()Returns the accumulated pending text content
addEntry(entry: IHistoryEntry)Appends a pre-built IHistoryEntry to history (used for event entries such as tool summaries).
getHistory()Returns the full history as IHistoryEntry[]. Each chat message wraps a TUniversalMessage via data.

commitAssistant behavior:

  • Text content is ALWAYS preserved — no stripping, even when tool calls are present. Context savings is compaction's job.
  • The state parameter determines whether the committed message has state: 'complete' or state: 'interrupted'.
  • Single commit path — no branching between normal completion and abort.

getMessagesForAPI

getMessagesForAPI() prepares the conversation history for provider API calls. For interrupted assistant messages (state: 'interrupted'), the text is annotated with [This response was interrupted by the user] suffix. This allows the model to understand that its previous response was cut short.

executeRound Streaming Flow

The executeRound function manages streaming through ConversationStore:

  1. beginAssistant() initializes pending state before the provider call.
  2. Provider's onTextDelta callback is wrapped to call appendStreaming(delta) on each delta.
  3. After the provider returns: tool calls are added via appendToolCall(toolCall).
  4. commitAssistant(state, metadata?) is called with state determined by signal.aborted'interrupted' if aborted, 'complete' otherwise.
  5. Single commit path — no branching between normal and abort flows.

Extension Points

ExtensionBase ClassContract
AI ProviderAbstractAIProviderImplement chat(), chatStream()
ToolAbstractToolImplement execute(), provide schema
PluginAbstractPluginOverride lifecycle hooks
ModuleAbstractModuleImplement execute()
ExecutorAbstractExecutorImplement execute(), executeStream()
StoragePer-plugin interfacesImplement storage adapter (memory, file, remote)

Error Taxonomy

All errors extend RobotaError with code, category, and recoverable properties:

Error ClassCodeCategoryRecoverable
ConfigurationErrorCONFIGURATION_ERRORuserno
ValidationErrorVALIDATION_ERRORuserno
ProviderErrorPROVIDER_ERRORprovideryes
AuthenticationErrorAUTHENTICATION_ERRORuserno
RateLimitErrorRATE_LIMIT_ERRORprovideryes
NetworkErrorNETWORK_ERRORsystemyes
ToolExecutionErrorTOOL_EXECUTION_ERRORsystemno
ModelNotAvailableErrorMODEL_NOT_AVAILABLEuserno
CircuitBreakerOpenErrorCIRCUIT_BREAKER_OPENsystemyes
PluginErrorPLUGIN_ERRORsystemno
StorageErrorSTORAGE_ERRORsystemyes

ErrorUtils provides isRecoverable(), getErrorCode(), fromUnknown(), and wrapProviderError().

Execution Loop Error Handling

When the execution loop ends without a final assistant text message (e.g., due to max round limit or context overflow during tool execution):

  1. Force a final summary call — inject a synthetic user message requesting the AI to respond with what it has so far, noting what remains incomplete and that the user can follow up. Call provider.chat() WITHOUT tools (preventing further tool calls). The system message from config must be included. Use streaming (onTextDelta) if available.
  2. Preserve conversation history — strip the synthetic user message from history after the provider call completes so it doesn't pollute future turns.
  3. Fallback on empty response — if the forced call produces no text, return: "Maximum rounds reached. Partial results available in conversation history.".
  4. If the forced call throws — catch the error and return the fallback message without re-throwing.

Pre-Send Context Check

Before each provider.chat() call in the execution loop, token usage is checked against the model's context window limit. The estimate uses Math.max(cumulativeInputTokens, chars/2) — the higher of the API-reported token count and the character-based estimate. chars/2 (not chars/3) is used because Korean text, JSON, and code content have a higher char-to-token ratio. If usage exceeds 83.5% of the context window, the execution loop stops early with a clear assistant message prompting the user to /compact.

Provider Error Recovery

If provider.chat() throws an error (e.g., API 400 for context too large), executeRound catches it and injects an assistant message with the error. This ensures the user always sees a readable error message rather than "No response received." If the entire execution pipeline throws, ExecutionService.execute() catches it and returns a graceful error result instead of re-throwing.

AbstractAIProvider.streamWithAbort

streamWithAbort() is a protected async generator on AbstractAIProvider that wraps any async iterable with cooperative abort checking. All provider implementations MUST use this method for streaming iteration.

Mechanism:

  1. For each event from the source iterable, yields with a setTimeout(0) interleave to allow the event loop to process abort signals.
  2. Checks signal.aborted after each yield — breaks out of the loop if aborted.
  3. Providers wrap their SDK stream with this.streamWithAbort(stream, signal) in their chatWithStreaming implementation.

Usage pattern (in provider):

typescript
for await (const event of this.streamWithAbort(stream, signal)) {
  // process event
}
// After loop: check signal.aborted to determine stopReason

This ensures all providers have consistent, low-latency abort responsiveness without duplicating the abort-checking logic.

Tool Result Context Budget

After the assistant message is committed to history, tool results are added to history one by one. After each addition, the estimated token count (chars/2) is checked against 80% of the model's context window.

If exceeded, remaining tool results are replaced with a short context-error message (permission-deny pattern):

Error: Context window near capacity. Tool execution result skipped.

Key behavior:

  • Follows the permission-deny pattern — AI receives a mix of normal results and context-error results
  • The execution loop does NOT break — it continues to the next provider call so the AI can see the mixed results and respond
  • AI autonomously decides how to handle: partial answer from available results, retry with fewer tools, etc.
  • Skipped tool results are short error messages (~80 chars), so the next provider call succeeds

Example flow:

[assistant] text + tool_use(Read, Bash, Glob, Write)
[tool] Read result (normal, context at 75%)
[tool] Bash result (normal, context at 82% → overflow detected)
[tool] Glob: "Error: Context window near capacity. Tool execution result skipped."
[tool] Write: "Error: Context window near capacity. Tool execution result skipped."
→ next provider call succeeds
→ AI responds based on Read and Bash results, notes Glob and Write were skipped

Return value: addToolResultsToHistory returns IToolResultsOutcome with contextOverflowed, addedCount, and skippedCount.

Streaming Round Separator

When the execution loop starts round 2+ (after tool execution), execution-round.ts emits '\n\n' through provider.onTextDelta before calling provider.chat(). This separates streaming text from different rounds in the CLI, which would otherwise concatenate without line breaks.

Class Contract Registry

Interface Implementations

InterfaceImplementorKindLocation
IAgentAbstractAgentabstract basesrc/abstracts/abstract-agent.ts
IAgentRobotaproductionsrc/core/robota.ts
IAIProviderAbstractAIProviderabstract basesrc/abstracts/abstract-ai-provider.ts
IExecutorAbstractExecutorabstract basesrc/abstracts/abstract-executor.ts
IPluginContract, IPluginHooksAbstractPluginabstract basesrc/abstracts/abstract-plugin.ts
IToolWithEventServiceAbstractToolabstract basesrc/abstracts/abstract-tool.ts
IModule, IModuleHooksAbstractModuleabstract basesrc/abstracts/abstract-module.ts
IWorkflowConverterAbstractWorkflowConverterabstract basesrc/abstracts/abstract-workflow-converter.ts
IWorkflowValidatorAbstractWorkflowValidatorabstract basesrc/abstracts/abstract-workflow-validator.ts
IEventServiceAbstractEventServiceabstract basesrc/event-service/event-service.ts
IEventServiceDefaultEventServiceproduction (null object)src/event-service/event-service.ts
IEventServiceStructuredEventServiceproductionsrc/event-service/event-service.ts
IEventServiceObservableEventServiceproductionsrc/event-service/event-service.ts
IConversationHistoryConversationHistoryproductionsrc/managers/conversation-history-manager.ts
IConversationHistoryConversationStoreproductionsrc/managers/conversation-store.ts
IConversationServiceConversationServiceproductionsrc/services/conversation-service/index.ts
IToolManagerToolsproductionsrc/managers/tool-manager.ts
IAIProviderManagerAIProvidersproductionsrc/managers/ai-provider-manager.ts
IPluginsManagerPluginsproductionsrc/managers/plugins.ts
ILoggerConsoleLoggerproductionsrc/utils/logger.ts
IEventHistoryModuleEventHistoryModuleproductionsrc/services/history-module.ts
IEventHistoryModuleInMemoryHistoryStoreproductionsrc/services/in-memory-history-store.ts
IEventEmitterMetricsInMemoryEventEmitterMetricsproductionsrc/plugins/event-emitter/metrics.ts
ICacheStorageMemoryCacheStorageproductionsrc/services/cache/memory-cache-storage.ts

NOTE: FunctionTool, ToolRegistry, OpenAPITool moved to @robota-sdk/agent-tools. MCPTool, RelayMcpTool moved to @robota-sdk/agent-tool-mcp. Plugin storage implementations (ILogStorage, IUsageStorage, IPerformanceStorage, IHistoryStorage, etc.) moved to their respective @robota-sdk/agent-plugin-* packages.

Inheritance Chains (within agent-core)

BaseDerivedLocationNotes
AbstractAgentRobotasrc/core/robota.tsMain facade
AbstractEventServiceDefaultEventServicesrc/event-service/event-service.tsNull object
AbstractEventServiceStructuredEventServicesrc/event-service/event-service.tsOwner-bound events
AbstractEventServiceObservableEventServicesrc/event-service/event-service.tsRxJS integration
AbstractExecutorLocalExecutorsrc/executors/local-executor.tsLocal provider execution
AbstractPluginEventEmitterPluginsrc/plugins/event-emitter-plugin.tsEvent coordination

NOTE: Tool implementations (FunctionTool, OpenAPITool) in @robota-sdk/agent-tools implement IFunctionTool/ITool directly without extending AbstractTool. Plugin implementations in @robota-sdk/agent-plugin-* extend AbstractPlugin.

Cross-Package Port Consumers

Port (Owner)Adapter (Consumer Package)Location
AbstractAIProvider (agent-core)OpenAIProvider (agent-provider-openai)packages/agent-provider-openai/src/provider.ts
AbstractAIProvider (agent-core)AnthropicProvider (agent-provider-anthropic)packages/agent-provider-anthropic/src/provider.ts
AbstractAIProvider (agent-core)GoogleProvider (agent-provider-google)packages/agent-provider-google/src/provider.ts
AbstractAIProvider (agent-core)MockAIProvider (agent-sessions)packages/agent-sessions/examples/verify-offline.ts
AbstractExecutor (agent-core)SimpleRemoteExecutor (agent-remote)packages/agent-remote/src/client/remote-executor-simple.ts

Test Strategy

Current Coverage

LayerTest FilesCoverage
Core (Robota)robota.test.tsCore flow
Executorslocal-executor.test.tsLocal execution
Managersagent-factory.test.ts, tool-manager.test.ts, conversation-history-manager.test.tsCreation, tools, history
Pluginsevent-emitter-plugin.test.tsEvent coordination
Servicesevent-service.test.ts, execution-service.test.tsEvents, execution

Scenario Verification

  • Command: pnpm scenario:verify (runs examples/verify-offline.ts with MockAIProvider)
  • Record: examples/scenarios/offline-verify.record.json
  • Validates: agent creation, tool registration, conversation flow without network

Coverage Gaps (Improvement Targets)

  • Service edge cases: tool-execution-service, task-events, user-events
  • Utility tests: errors, validation, message-converter
  • NOTE: Plugin tests belong to @robota-sdk/agent-plugin-* packages. Tool tests belong to @robota-sdk/agent-tools.

Dependencies

Production (2)

  • jssha — SHA hashing for content verification
  • zod — Schema validation for tool parameters

Key Peer Contracts

  • Provider packages implement AbstractAIProvider and IAIProvider
  • @robota-sdk/agent-sessions consumes Robota, runHooks, evaluatePermission, TUniversalMessage
  • @robota-sdk/agent-tools consumes AbstractTool, IFunctionTool, IToolWithEventService
  • @robota-sdk/agent-plugin-* packages extend AbstractPlugin
  • @robota-sdk/agent-team consumes Robota, IAgentConfig, event services

Released under the MIT License.