npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

openmolt

v0.1.5

Published

Programmatic AI Agent System – create, configure, and run intelligent agents that can use tools, integrations, and LLMs.

Downloads

526

Readme

OpenMolt

Programmatic AI Agent System for Node.js / TypeScript

OpenMolt lets your code create autonomous AI agents that plan, reason, and act — calling real APIs, reading files, generating images, sending messages, and more. Agents run a self-directed reasoning loop (the Maestro loop) powered by any LLM until the task is complete.

npm install openmolt

openmolt.dev — full documentation, API reference, and examples


Why OpenMolt?

| | | |---|---| | Secure by design | Agents access only the scopes you grant. The LLM sees tool names — never raw credentials | | Multi-provider | OpenAI, Anthropic Claude, and Google Gemini with a unified provider:model string | | 30+ built-in integrations | Gmail, Slack, GitHub, Notion, Stripe, Discord, S3, and more — ready out of the box | | Declarative HTTP tools | Define integrations as data (endpoint, auth, Liquid templates) — no boilerplate | | Typed output | Pass a Zod schema; agent.run() returns a validated, typed object | | Scheduling | Interval and cron-style daily schedules with timezone support | | Events | Observable reasoning loop — hook into every tool call, plan update, and LLM output | | Memory | Long-term and short-term memory stores with onUpdate persistence callbacks | | CLI | npx openmolt agent.json to run agents from a config file |

Secure by Design

OpenMolt was built with security as a first-class constraint, not an afterthought.

Scope-gated tools. Every integration is granted an explicit list of scopes when you attach it to an agent. If a tool requires the write scope and you only granted read, the agent cannot call it — regardless of what the LLM decides.

integrations: [
  {
    integration: 'gmail',
    credential: { type: 'oauth2', config: { ... } },
    scopes: ['read'],   // agent can read emails, but cannot send or delete
  },
],

Credentials never reach the LLM. The model only sees tool names and their input/output schemas. Your API keys, tokens, and OAuth secrets are resolved server-side at execution time — the LLM prompt contains none of them.

Directory-restricted filesystem. The FileSystem integration is a factory that you instantiate with an explicit allowlist of directories. The agent cannot read or write outside those paths.

om.registerIntegration('fileSystem', OpenMolt.FileSystemIntegration('./output'));
// agent cannot access /etc, ~/, or any path outside ./output

No implicit network access. Agents can only call APIs that are registered as integrations. There is no general-purpose outbound HTTP unless you explicitly add the httpRequest integration.


Quick Start

import OpenMolt from 'openmolt';

const om = new OpenMolt({
  llmProviders: {
    openai: { apiKey: process.env.OPENMOLT_OPENAI_API_KEY },
  },
});

const agent = om.createAgent({
  name: 'Comedian',
  model: 'openai:gpt-4o-mini',
  instructions: 'You are a witty stand-up comedian.',
});

const result = await agent.run('Tell me a joke!');
console.log(result);

Environment variables (no config needed):

| Variable | Provider | |---|---| | OPENMOLT_OPENAI_API_KEY | OpenAI | | OPENMOLT_ANTHROPIC_API_KEY | Anthropic | | OPENMOLT_GOOGLE_API_KEY | Google Gemini |


Model Strings

Choose any LLM with provider:model-name:

model: 'openai:gpt-4o'
model: 'openai:o3-mini'
model: 'anthropic:claude-opus-4-6'
model: 'anthropic:claude-sonnet-4-6'
model: 'google:gemini-2.0-flash'
model: 'google:gemini-2.5-pro'

Optional per-model config:

modelConfig: {
  thinking: true,      // Extended thinking (Anthropic / Gemini)
  search: true,        // Grounded web search (Gemini)
  temperature: 0.7,
}

Examples

Structured output with a Zod schema

import { z } from 'zod';
import OpenMolt from 'openmolt';

const om = new OpenMolt({ llmProviders: { openai: {} } });

const LogoSchema = z.object({
  logoUrl:    z.string().url(),
  altText:    z.string().optional(),
  confidence: z.enum(['high', 'medium', 'low']),
});

const agent = om.createAgent({
  name: 'LogoExtractor',
  model: 'openai:gpt-4o',
  instructions: 'Fetch the page with httpRequest and extract the logo URL.',
  integrations: [
    { integration: 'httpRequest', credential: { type: 'custom', config: {} }, scopes: 'all' },
  ],
  outputSchema: LogoSchema,
});

const result = await agent.run('https://example.com') as z.infer<typeof LogoSchema>;
console.log(result.logoUrl, result.confidence);

Gmail draft generator that runs on a schedule

import OpenMolt from 'openmolt';

const om = new OpenMolt({ llmProviders: { openai: {} }, maxSteps: 30 });

const agent = om.createAgent({
  name: 'GmailDraftBot',
  model: 'openai:gpt-4o',
  instructions: `
    Fetch the 10 most recent unread emails.
    For each one, draft a professional reply using gmail → createDraft.
    Finish with a summary of how many drafts were created.
  `,
  integrations: [
    {
      integration: 'gmail',
      credential: {
        type: 'oauth2',
        config: {
          clientId:     process.env.GOOGLE_CLIENT_ID ?? '',
          clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? '',
          refreshToken: process.env.GOOGLE_REFRESH_TOKEN ?? '',
        },
        onTokenRefresh: async (newConfig) => { /* persist tokens */ },
      },
      scopes: 'all',
    },
  ],
});

agent.on('tool:call', ({ tool }) =>
  console.log(`[tool] ${tool.integration}.${tool.handle}`)
);

// Run once now, then every 20 minutes
await agent.run('Process unread emails.');
const id = agent.schedule({ type: 'interval', value: 20 * 60 });

process.on('SIGINT', () => { agent.cancelSchedule(id); process.exit(0); });

Blog post writer with AI-generated images

import OpenMolt from 'openmolt';

const om = new OpenMolt({ llmProviders: { openai: {} }, maxSteps: 40 });

// Restrict filesystem access to ./blog only
om.registerIntegration('fileSystem', OpenMolt.FileSystemIntegration('./blog'));

const agent = om.createAgent({
  name: 'BlogWriter',
  model: 'openai:gpt-4o',
  instructions: `
    1. Write a full Markdown blog post with front-matter.
    2. Generate 2-3 images with fal → generate (fal-ai/flux/schnell).
    3. Save the .md file to fileSystem with the fal CDN image URLs inline.
    4. Finish with the output path and image URLs.
  `,
  integrations: [
    { integration: 'fal',        credential: { type: 'bearer', config: { apiKey: process.env.FAL_API_KEY ?? '' } }, scopes: 'all' },
    { integration: 'fileSystem', credential: { type: 'custom', config: {} }, scopes: ['read', 'write'] },
  ],
});

const result = await agent.run('Write a blog post about the future of AI agents.');
console.log(result);

Custom integration (declarative HTTP)

import OpenMolt, { IntegrationDefinition } from 'openmolt';
import { z } from 'zod';

const weatherDefinition: IntegrationDefinition = {
  name: 'Weather',
  apiSetup: {
    baseUrl: 'https://api.openweathermap.org/data/2.5',
    headers: { 'Content-Type': 'application/json' },
    responseFormat: 'json',
  },
  credentialSetup: [{ type: 'custom', queryParams: { appid: '{{ config.apiKey }}' } }],
  tools: [
    {
      handle: 'getCurrentWeather',
      description: 'Get current weather for a city.',
      method: 'GET',
      endpoint: '/weather',
      queryParams: { q: '{{ input.city }}', units: 'metric' },
      inputSchema:  z.object({ city: z.string() }),
      outputSchema: z.object({ temp: z.number(), description: z.string() }),
    },
  ],
};

const om = new OpenMolt({ llmProviders: { anthropic: {} } });
om.registerIntegration('weather', weatherDefinition);

const agent = om.createAgent({
  name: 'WeatherBot',
  model: 'anthropic:claude-sonnet-4-6',
  instructions: 'Answer questions about the current weather.',
  integrations: [
    { integration: 'weather', credential: { type: 'custom', config: { apiKey: process.env.WEATHER_API_KEY ?? '' } }, scopes: 'all' },
  ],
});

console.log(await agent.run('What is the weather in Tokyo?'));

Daily scheduling with memory

const agent = om.createAgent({
  name: 'ReportBot',
  model: 'google:gemini-2.0-flash',
  instructions: 'Pull metrics from Stripe and post a daily summary to Slack.',
  memory: {
    longTerm: {
      data: '',
      onUpdate: async (data) => await fs.writeFile('memory.txt', data),
    },
  },
  integrations: [
    { integration: 'stripe', credential: { type: 'bearer', config: { apiKey: process.env.STRIPE_SECRET_KEY ?? '' } }, scopes: 'all' },
    { integration: 'slack',  credential: { type: 'bearer', config: { apiKey: process.env.SLACK_BOT_TOKEN ?? '' } },  scopes: 'all' },
  ],
});

// Every weekday at 9 AM New York time
agent.schedule({
  type: 'daily',
  dayOfWeek: [1, 2, 3, 4, 5],
  hour: 9, minute: 0,
  timeZone: 'America/New_York',
});

Built-in Integrations

| Category | Integrations | |---|---| | Productivity | Notion, Airtable, Google Calendar, Google Drive, Google Sheets, Microsoft Outlook | | Communication | Gmail, Slack, Discord, Telegram, WhatsApp, Twilio | | Social / Content | X (Twitter), Instagram, TikTok, YouTube | | AI / Media | fal.ai, Google Imagen + Veo (Gemini Media Models), OpenAI Media Models (DALL-E / gpt-image-1) | | Commerce | Stripe, Shopify, Etsy | | Dev & Cloud | GitHub, AWS S3, Dropbox | | Ads | Google Ads, Meta Ads | | Web | browser-use.com (cloud browsing), Generic HTTP Request | | Local | FileSystem (directory-restricted) |


Events

Observe every step of the agent's reasoning:

agent.on('llmOutput',      ({ output })         => console.log('LLM tokens used:', output.usage));
agent.on('commandsQueued', ({ commands })        => console.log('Next commands:', commands.length));
agent.on('tool:call',      ({ tool })            => console.log('Calling:', tool.integration, tool.handle));
agent.on('tool:response',  ({ tool, response })  => console.log('Response:', response));
agent.on('planUpdate',     ({ plan })            => console.log('Plan updated:', plan));
agent.on('finish',         ({ result })          => console.log('Done:', result));

CLI

Run an agent from a JSON or JS config file:

npx openmolt agent.json
npx openmolt agent.json --input "Summarise this week's Stripe revenue" --verbose
npx openmolt agent.json --dry-run   # validate without running

agent.json

{
  "llmProviders": { "openai": { "apiKey": "sk-..." } },
  "integrations": { "slack": { "apiKey": "xoxb-..." } },
  "agent": {
    "name": "SlackBot",
    "model": "openai:gpt-4o",
    "instructions": "Post a motivational message to #general every morning.",
    "integrations": [
      { "integration": "slack", "credential": { "type": "bearer", "config": {} }, "scopes": "all" }
    ],
    "schedules": [
      { "type": "daily", "hour": 8, "minute": 0, "timeZone": "UTC" }
    ]
  }
}

Documentation

Full docs, API reference, and more examples at openmolt.dev.


License

MIT