The Problem
You've written this function
more than once.
And you'll write it again. Here's why.
Every protocol is another copy
HTTP, WebSocket, queues, CLI, SSE — each one gets its own handler. They start as copies but drift apart. Auth gets fixed in one place, not the others. Bugs multiply in silence.
Workflows, agents, and MCP are always extra work
Wiring a function to a workflow engine, an AI agent, or an MCP server means adapters, schema re-definitions, and another auth layer to maintain — even for logic you've already shipped.
Switching infrastructure means rewriting
Going from Express to Lambda, or Cloudflare Workers to a container, touches every handler. Your business logic ends up tangled with framework APIs you never wanted to care about.
One function. Every protocol.
Write your business logic once. Pikku wires it to any protocol — same auth, same permissions, no rewrites.
Write once
const getCard = pikkuFunc({
title: 'Get Card',
description: 'Retrieve a card by ID',
func: async ({ db, audit }, { cardId }) => {
const card = await db.getCard(cardId)
await audit.log('getCard', { cardId })
return card
},
permissions: { user: isAuthenticated }
})
Pick a protocol


Wiring code
wireHTTP({
method: 'get',
route: '/cards/:cardId',
func: getCard
})
Your functions are already agent tools
No adapters. No schema writing. No separate auth layer. Pass your existing Pikku functions directly — the agent gets your full backend.
// These already exist in your backend — no changes needed
import { getCustomer, getOrders, createTicket } from './functions'
export const supportAgent = pikkuAgent({
name: 'support',
instructions: `You are a helpful support agent.
Look up the customer's account and recent orders.`,
tools: [getCustomer, getOrders, createTicket],
model: 'claude-sonnet-4-5'
})
// Wire it just like any HTTP endpoint
wireHTTP({
method: 'post',
route: '/api/chat',
func: supportAgent
})
Zero glue code
Pass any Pikku function as a tool — the agent inherits its type signature, description, and input schema automatically. No adapters, no wrappers, no manual schema definitions.
Auth follows the agent
Agents inherit the caller's session, permissions, and middleware. The same rules that protect your HTTP endpoints automatically protect every tool the agent can call — no separate security layer to build or maintain.
Any LLM, same interface
Bring OpenAI, Anthropic, or any provider. Pikku handles tool calling, streaming, and context — you just swap the model name.
Multi-step processes that
survive anything
Write sequential logic like normal code. Pikku handles persistence, retries, and resumption — even across server restarts.
Deterministic replay
Completed steps are cached and never re-executed. A workflow that fails on step 4 resumes from step 4 — not from the beginning.
Sleep for hours, days, or weeks
workflow.sleep('5min') suspends execution without holding a server connection. Perfect for trial expirations, reminders, and follow-ups.
Survives restarts
State is persisted to PostgreSQL or Redis between steps. Deploy a new version mid-workflow and execution continues from where it left off.
export const onboardingWorkflow = pikkuWorkflowFunc(
async ({ workflow }, { email, userId }) => {
// Each step is persisted — safe to retry
const user = await workflow.do(
'Create user profile',
'createUserProfile',
{ email, userId }
)
await workflow.do(
'Add to CRM',
async () => crm.createUser(user)
)
// Suspend for 5 minutes — no server held
await workflow.sleep('Wait before welcome email', '5min')
await workflow.do(
'Send welcome email',
'sendEmail',
{ to: email, template: 'welcome' }
)
return { success: true }
}
)
See your entire backend
from one place
The Pikku Console gives every environment its own control plane — browse functions, run agents, manage secrets, and trigger workflows without writing a line of tooling code.

Install a backend feature
in one line
Addons are drop-in function packages — Stripe, Postgres, SendGrid, and more. Install, configure secrets, call via namespaced RPC. Fully typed.
// One line per addon
wireAddon({
name: 'stripe',
package: '@pikku/addon-stripe'
})
wireAddon({
name: 'email',
package: '@pikku/addon-sendgrid',
secretOverrides: {
SENDGRID_API_KEY: 'MY_EMAIL_KEY'
}
})
// Call addon functions via namespaced RPC
const checkout = pikkuFunc({
func: async ({}, { plan }, { rpc }) => {
const session = await rpc.invoke(
'stripe:checkoutCreate',
{ plan, currency: 'usd' }
)
await rpc.invoke(
'email:mailSend',
{ to: session.email, template: 'receipt' }
)
return { url: session.url }
}
})
Drop-in, not bolt-on
Install a package, add one wireAddon() call, and its functions appear as namespaced RPC calls. No glue code, no adapters, no boilerplate.
Fully typed across boundaries
The CLI generates TypeScript definitions for every addon function. rpc.invoke('stripe:checkoutCreate', ...) is autocompleted with the exact input and output types.
Secrets you control
Addons declare what secrets they need. You map them to your own infrastructure with secretOverrides — no env vars leaking across packages.
Shared infrastructure
Addons reuse your existing logger, database, and services — no duplicate connections. Each addon gets its own namespace, so nothing collides.
Production-grade out of the box
Auth, validation, type-safe clients, middleware — all built in. No bolting on third-party packages or writing boilerplate for every new protocol.
Change your runtime.
Keep your functions.
Same code runs on Express, Fastify, AWS Lambda, Cloudflare Workers, Next.js, and more. Switching runtimes never requires touching your functions.
Plus any custom runtime via the adapter interface. Build your own →
Bundle Only What You Deploy
Run your codebase as a monolith, as microservices, or as functions. Pikku creates the smallest bundle for your use case.
Monolith
Run everything in one process
Microservices
Split by domain or feature
Functions
One function per deployment
Built for the problems developers actually have
From the teams who switched
"So many places in my code base have like three entry points: CLI, public (sometimes protected) HTTP API and internally from within the API. Would be so nice having everything just an invoke away. With Nest it's a pain because you basically have to start the whole API up just to run CLI command."
Alex Harley
Co-founder @ Superbridge
"Ever been annoyed at having to write your code different in a Lambda than in an express handler? Pikku fixes that."
Christoph Sitter
CTO @ spot
Your next backend shouldn't have eight copies of the same function.
Write it once. Pikku wires it everywhere.
MIT Licensed • Open Source • 5-minute setup
