Voices

The plugin ecosystem
is the framework.

13 official voices ship today — 107 tools across filesystem, browser, code execution, GitHub, Postgres, Stripe, messaging, and more. Need something else? Bridge any MCP server with the @tuttiai/mcp voice, or build and publish your own to npm. Every voice is semver-versioned and declares its own permission scopes — the runtime enforces them.

13
official voices
107
tools shipped
any
MCP server, bridged
open
contributions welcome
Kind
More on the way

Don't see what you need? Bridge it, or build it.

Tutti is open source and the roster grows in two ways. Wrap any MCP server with @tuttiai/mcp and its tools become a typed Tutti voice instantly — no PR required. For everything else, voices are plain TypeScript: implement the Voice interface, publish to npm, and open an issue if you'd like it listed here. We review and welcome community voices.

Build your own

A typed voice in 20 lines.

Voices are plain TypeScript classes. Declare tool schemas with Zod, declare permissions, ship to npm. The runtime handles invocation, retries, redaction, and tracing.

Zod schemasdeclared permissionsauto-redactionOTEL spansdestructive flagrate-limit aware
Read the authoring guide →
import type { Voice, Tool } from '@tuttiai/types'
import { z } from 'zod'

const get_forecast: Tool = {
  name: 'get_forecast',
  description: 'Forecast for a city.',
  parameters: z.object({ city: z.string() }),
  execute: async ({ city }) => {
    const r = await fetch(`https://api.weather.com/${city}`)
    return { content: await r.text() }
  },
}

export const WeatherVoice: Voice = {
  name: 'weather',
  required_permissions: ['network'],
  tools: [get_forecast],
}

Start conducting.

One install. Your first agent running in 60 seconds. No signup. No telemetry.