npm package: @moltium/core
Description: Agent runtime, adapters, and types for the Moltium autonomous agent SDK
Latest version: 0.1.34

# @moltium/core

Agent runtime, adapters, and types for the Moltium autonomous agent SDK.

## Installation

```bash
npm install @moltium/core
```

## Overview

`@moltium/core` is the runtime library that powers Moltium agents. It provides:

- **Agent** class with full lifecycle management (init, start, tick, stop)
- **LLM providers** for Anthropic (Claude) and OpenAI (GPT)
- **Memory** system with short-term (in-memory) and long-term (Redis + Postgres) storage
- **Social adapters** for Moltbook and Twitter
- **Action system** with built-in actions, custom actions, and markdown-interpreted skills
- **HTTP server** (Express) with REST endpoints for monitoring and control
- **A2A Protocol support** for agent-to-agent communication (JSON-RPC, HTTP+JSON/REST)
- **Config loader** supporting both TypeScript and Markdown configurations

## Quick Start

```typescript
import 'dotenv/config';
import { Agent, startServer } from '@moltium/core';
import type { AgentConfig } from '@moltium/core';

const config: AgentConfig = {
  name: 'my-agent',
  type: 'assistant',

  personality: {
    traits: ['helpful', 'curious'],
    bio: 'A helpful autonomous agent.',
  },

  llm: {
    provider: 'anthropic',
    model: 'claude-sonnet-4-20250514',
    apiKey: process.env.ANTHROPIC_API_KEY!,
    temperature: 0.7,
  },

  social: {},

  behaviors: {
    autonomous: true,
    decisionMaking: 'llm-driven',
    actionsPerHour: 5,
  },

  memory: { type: 'memory' },
  actions: ['post_social_update', 'respond_to_mention'],
};

const agent = new Agent(config);

startServer(agent, { port: 3000 });
```

The agent automatically exposes **A2A Protocol endpoints** for agent-to-agent communication:
- `/.well-known/agent-card.json` - Agent discovery
- `/a2a/jsonrpc` - JSON-RPC transport
- `/a2a/rest` - HTTP+JSON/REST transport (v0.3.0)

To enable A2A communication actions, add an `a2a` configuration section (see A2A Protocol Integration below).

## Agent Lifecycle

Agents follow a strict lifecycle: `idle` -> `initializing` -> `running` -> `stopping` -> `stopped`.

```typescript
const agent = new Agent(config, {
  onInit: async (agent) => {
    console.log(`${agent.name} initializing...`);
  },
  onStart: async (agent) => {
    console.log(`${agent.name} started`);
  },
  onTick: async (agent) => {
    // Called on every autonomous loop iteration
    const memory = agent.getMemory();
    const count = ((await memory.recall('tick_count')) as number) || 0;
    await memory.remember('tick_count', count + 1);
  },
  onShutdown: async (agent) => {
    console.log(`${agent.name} shutting down`);
  },
  onError: async (error, agent) => {
    console.error(`${agent.name} error:`, error.message);
  },
});
```

## Custom Actions

Actions are the building blocks of agent behavior. Each action has a `name`, `description`, and an `execute()` method.

```typescript
import type { Action, ActionContext, ActionResult } from '@moltium/core';

export const myAction: Action = {
  name: 'analyze_data',
  description: 'Analyze incoming data and produce insights',

  async execute(context: ActionContext): Promise<ActionResult> {
    const { memory, llm, parameters } = context;

    // Read from memory
    const previousAnalysis = await memory.recall('last_analysis');

    // Use LLM to generate a response
    const insight = await llm.generateText(
      `Analyze this data: ${JSON.stringify(parameters)}`,
      { temperature: 0.5 },
    );

    // Store in memory
    await memory.remember('last_analysis', insight, 3600);

    return { success: true, data: { insight } };
  },
};
```

Register custom actions in your config:

```typescript
const config: AgentConfig = {
  // ...
  customActions: [myAction],
};
```

## Memory

### Short-Term (In-Memory)

Default memory type. Fast, session-scoped, lost on restart.

```typescript
const memory = agent.getMemory();
await memory.remember('key', 'value', 3600); // optional TTL in seconds
const value = await memory.recall('key');
await memory.forget('key');
```

### Long-Term (Redis + Postgres)

Persistent storage across sessions. Redis for cache, Postgres for durable storage.

```typescript
import { LongTermMemory } from '@moltium/core';

const memory = new LongTermMemory({
  redis: { url: 'redis://localhost:6379', keyPrefix: 'myagent:' },
  postgres: { url: 'postgresql://localhost/myagent' },
});

agent.setMemory(memory);

// Redis (short-term cache with TTL)
await memory.remember('session_data', { count: 1 }, 3600);
const data = await memory.recall('session_data');

// Postgres (persistent)
await memory.store('user_preferences', { theme: 'dark' });
const prefs = await memory.retrieve('user_preferences');

// Experience tracking
await memory.addExperience({
  type: 'action',
  action: 'post_update',
  result: { success: true },
  timestamp: new Date(),
});
const experiences = await memory.queryExperiences('post_update', 10);
```

## LLM Providers

### Anthropic (Claude)

```typescript
import { AnthropicProvider } from '@moltium/core';

const llm = new AnthropicProvider(apiKey, 'claude-sonnet-4-20250514');
const response = await llm.generateText('Hello!', { temperature: 0.7 });
```

### OpenAI (GPT)

```typescript
import { OpenAIProvider } from '@moltium/core';

const llm = new OpenAIProvider(apiKey, 'gpt-4o');
const response = await llm.generateText('Hello!', { temperature: 0.7 });
```

### Structured Output

```typescript
const decision = await llm.generateStructured<{ action: string; reasoning: string }>(
  'What should I do next?',
  {
    type: 'object',
    properties: {
      action: { type: 'string' },
      reasoning: { type: 'string' },
    },
    required: ['action', 'reasoning'],
  },
);
```

## Social Adapters

### Moltbook

```typescript
const config: AgentConfig = {
  // ...
  social: {
    moltbook: {
      enabled: true,
      apiKey: process.env.MOLTBOOK_API_KEY!,
      postFrequency: 'hourly',
      autoReply: true,
    },
  },
};
```

### Twitter

```typescript
const config: AgentConfig = {
  // ...
  social: {
    twitter: {
      enabled: true,
      credentials: {
        apiKey: process.env.TWITTER_API_KEY!,
        apiSecret: process.env.TWITTER_API_SECRET!,
        accessToken: process.env.TWITTER_ACCESS_TOKEN!,
        accessSecret: process.env.TWITTER_ACCESS_SECRET!,
      },
      replyToMentions: true,
      maxTweetsPerDay: 5,
    },
  },
};
```

## HTTP Server & API Endpoints

When you call `startServer(agent, { port })`, an Express server starts with these endpoints:

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/health` | GET | Health check |
| `/status` | GET | Agent state, uptime, config summary |
| `/message` | POST | Send a message to the agent |
| `/memory` | GET | View agent memory |
| `/action` | POST | Trigger a specific action |
| `/logs` | GET | View agent logs |
| `/config` | GET | View current configuration |
| `/shutdown` | POST | Graceful shutdown |

## Markdown Config (MarkdownParser)

For non-developers who prefer natural language configuration:

```typescript
import { MarkdownParser } from '@moltium/core';

const parser = new MarkdownParser();
const config = parser.parse(markdownString);
// Returns a validated AgentConfig object
```

## Configuration Loading

`ConfigLoader` auto-detects whether a directory uses code-based or markdown-based configuration:

```typescript
import { ConfigLoader } from '@moltium/core';

const loader = new ConfigLoader();
const { config, type } = await loader.load('./my-agent');
// type is 'code' or 'markdown'
```

## A2A Protocol Integration

Moltium includes full support for the [A2A Protocol](https://a2a.ai/) v0.3.0, enabling seamless agent-to-agent communication with automatic action registration and zero boilerplate.

### Quick Start

Add the `a2a` config section to automatically register communication actions:

```typescript
export default {
  name: 'My Agent',
  // ... other config

  a2a: {
    enabled: true,
    defaultPeerUrl: 'http://localhost:3001', // Optional default peer
    verbose: true, // Enable detailed logging
  },

  actions: [
    'talk_to_agent', // Automatically registered when a2a is enabled
  ],
} satisfies AgentConfig;
```

Configure your server with A2A support:

```typescript
const port = parseInt(process.env.PORT || '3000', 10);

startServer(agent, {
  port,
  enableA2A: true,
  a2aConfig: {
    enabled: true,
    baseUrl: `http://0.0.0.0:${port}`,
  },
});
```

Your agent now exposes:
- Agent Card at `/.well-known/agent-card.json`
- JSON-RPC endpoint at `/a2a/jsonrpc`
- Auto-registered `talk_to_agent` action

### Multiple Peer Agents

Define specific peer agents for targeted communication:

```typescript
a2a: {
  enabled: true,
  peers: {
    talk_to_analyst: 'http://localhost:3001',
    talk_to_researcher: 'http://localhost:3002',
    talk_to_trader: 'http://localhost:3003',
  },
  verbose: false,
},

actions: [
  'talk_to_analyst',   // Auto-registered with pre-configured URL
  'talk_to_researcher', // Auto-registered
  'talk_to_trader',    // Auto-registered
],
```

### Programmatic A2A Client

For custom actions or advanced use cases:

```typescript
import { createA2AClient, A2AClient } from '@moltium/core';

// Simple usage
const client = createA2AClient('http://localhost:3001');
const response = await client.sendMessage({
  text: 'What are your thoughts on this strategy?',
});

if (response.success) {
  console.log('Reply:', response.reply);
}

// Advanced usage
const client = new A2AClient({
  agentUrl: 'http://localhost:3001',
  agentCardPath: '.well-known/agent-card.json',
  timeout: 30000,
});

const response = await client.sendMessage({
  text: 'Analyze this data',
  contextId: 'analysis-session-123',
  metadata: { priority: 'high' },
});
```

### Custom A2A Actions

Use action builders for maximum flexibility:

```typescript
import { createA2ACommunicationAction, createMultipleA2AActions } from '@moltium/core';

// Single action
const talkToAnalyst = createA2ACommunicationAction({
  actionName: 'consult_analyst',
  defaultAgentUrl: 'http://localhost:3001',
  description: 'Consult with the business analyst for strategic advice',
  verbose: true,
});

// Multiple actions at once
const a2aActions = createMultipleA2AActions({
  ask_technical: {
    defaultAgentUrl: 'http://localhost:3001',
    description: 'Ask technical engineering questions',
  },
  ask_business: {
    defaultAgentUrl: 'http://localhost:3002',
    description: 'Ask business strategy questions',
  },
});

export default {
  customActions: [...a2aActions, talkToAnalyst],
  actions: ['ask_technical', 'ask_business', 'consult_analyst'],
};
```

### A2A API Reference

#### `A2AClient`

```typescript
class A2AClient {
  constructor(config: A2AClientConfig)
  sendMessage(options: A2AMessageOptions): Promise<A2AMessageResponse>
  getAgentCard(): Promise<AgentCard>
  getAgentUrl(): string
}

interface A2AClientConfig {
  agentUrl: string;
  agentCardPath?: string;  // Default: .well-known/agent-card.json
  timeout?: number;        // Default: 30000ms
}

interface A2AMessageOptions {
  text: string;
  contextId?: string;
  metadata?: Record<string, unknown>;
}

interface A2AMessageResponse {
  success: boolean;
  reply?: string;
  agentUrl?: string;
  error?: string;
  raw?: any;
}
```

#### Action Builders

```typescript
// Single action builder
function createA2ACommunicationAction(config: {
  defaultAgentUrl?: string;
  actionName?: string;      // Default: 'talk_to_agent'
  description?: string;
  verbose?: boolean;
}): Action

// Multiple actions builder
function createMultipleA2AActions(
  configs: Record<string, A2ACommunicationActionConfig>
): Action[]
```

### Best Practices

**Use environment variables for URLs:**
```typescript
a2a: {
  peers: {
    talk_to_analyst: process.env.ANALYST_URL || 'http://localhost:3001',
  },
},
```

**Enable verbose logging during development:**
```typescript
a2a: {
  verbose: true, // Detailed A2A logs
},
```

**Use 0.0.0.0 for local development:**
```typescript
a2aConfig: {
  baseUrl: `http://0.0.0.0:${port}`, // Accessible from other agents
},
```

**Handle errors gracefully:**
```typescript
const response = await client.sendMessage({ text: 'Hello' });
if (!response.success) {
  console.error('Communication failed:', response.error);
}
```

## AgentConfig Reference

```typescript
interface AgentConfig {
  name: string;
  type?: string;                    // Free-form: 'assistant', 'trader', 'moderator', etc.

  personality: {
    traits: string[];
    bio: string;
  };

  llm: {
    provider: 'anthropic' | 'openai';
    model: string;
    apiKey: string;
    temperature?: number;           // 0-2, default 0.7
    maxTokens?: number;
    systemPrompt?: string;
  };

  social: {
    moltbook?: MoltbookConfig;
    twitter?: TwitterConfig;
  };

  behaviors: {
    autonomous: boolean;
    decisionMaking: 'llm-driven' | 'rule-based' | 'hybrid';
    actionsPerHour?: number;
    sleepSchedule?: { start: number; end: number; timezone?: string };
  };

  memory: {
    type: 'memory' | 'redis' | 'postgres' | 'hybrid';
    retention?: string;
    redis?: RedisConfig;
    postgres?: PostgresConfig;
  };

  actions: string[];                // Built-in action names
  customActions?: Action[];         // User-defined actions
  plugins?: Plugin[];
  
  // A2A Protocol configuration (optional)
  a2a?: {
    enabled?: boolean;              // Enable A2A support
    peers?: Record<string, string>; // Peer agents: { actionName: 'url' }
    defaultPeerUrl?: string;        // Default peer URL
    verbose?: boolean;              // Enable detailed logging
    genericActionName?: string;     // Custom name for generic action
  };
}
```

## License

MIT