agentskit.js
Recipes

Recipe: Scaffolding with @agentskit/templates

Generate a build-ready AgentsKit package skeleton — tool, skill, adapter, embedder, memory, browser-adapter, or flow — in a few lines of Node.

@agentskit/templates is the programmatic authoring toolkit for extension packages. You can call its scaffolds directly from monorepo tasks, custom CLIs, or migration scripts.

Note: This package is not what agentskit init uses. The CLI has its own application starters. Use @agentskit/templates when you want to generate a build-ready tool/skill/adapter/memory/flow skeleton with AgentsKit contracts; complete its implementation stubs before publishing.

#Available shapes

ScaffoldTypeWhat lands on disk
toolToolDefinition skeleton + JSON Schema example.
skillSkillDefinition with system prompt + few-shot block.
adapterAdapterFactory skeleton + abort-signal wiring.
memory-vectorVectorMemory HTTP-backed skeleton with typed errors.
memory-chatChatMemory + real MemoryRecord via serializeMessages.
flowflow.yaml + named FlowRegistry export + smoke test.
embedderEmbedFn factory (OpenAI-compatible HTTP shape).
browser-adapterBrowser-only AdapterFactory with contract tests.

Every shape produces a build-ready package skeleton: package.json, tsconfig.json, tsup.config.ts, src/index.ts (named exports), tests/index.test.ts, README.md. Dependencies are minimal and caret-pinned — every package gets @agentskit/core ^1.0.0; only flow also adds @agentskit/runtime ^0.10.0. No wildcards; no unused deps.

#Quick start

import { scaffold } from '@agentskit/templates'

const created = await scaffold({
  type: 'adapter',
  name: 'my-llm',
  dir: './packages',
  description: 'Adapter for our internal inference proxy',
  // overwrite: false by default — existing dirs fail safely
})

console.log(`Wrote ${created.length} files into ./packages/my-llm`)
// Paths are final destinations (never staging paths).

#Name rules

Unscoped kebab-case only (my-llm). Scoped packages (@org/pkg) are intentionally unsupported in this beta line.

#Safety defaults

  • Config validated before any filesystem write
  • Symlink destination roots rejected
  • Sibling staging directory + atomic rename
  • Collision fails unless overwrite: true (backup + rollback)

#Programmatic factories

Per-type factories build a ToolDefinition / SkillDefinition / AdapterFactory in memory (no disk):

import {
  createToolTemplate,
  createSkillTemplate,
  createAdapterTemplate,
} from '@agentskit/templates'

const tool = createToolTemplate({
  name: 'lookup',
  description: 'Look up a customer by id',
  schema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
  execute: async ({ id }) => fetchCustomer(String(id)),
})

const skill = createSkillTemplate({
  name: 'researcher',
  description: 'Methodical web researcher.',
  systemPrompt: 'You are a methodical researcher…',
  tools: ['web_search', 'fetch_url'],
  metadata: { team: 'research' },
})

const adapter = createAdapterTemplate({
  name: 'echo',
  capabilities: { streaming: true, tools: false },
  createSource: () => ({
    stream: async function* () { yield { type: 'text', content: 'echo' }; yield { type: 'done' } },
    abort: () => {},
  }),
})

Each factory runs the matching validate*Template pass, so misshapen inputs throw at the call site instead of crashing the runtime later.

#Custom CLI integration

Wrap scaffold in your team's CLI to seed conventions:

#!/usr/bin/env node
import { scaffold, SCAFFOLD_TYPES } from '@agentskit/templates'
import { writeFile } from 'node:fs/promises'
import { join } from 'node:path'

const [type, name] = process.argv.slice(2)
if (!type || !name || !(SCAFFOLD_TYPES as readonly string[]).includes(type)) {
  console.error(`Usage: my-team-cli <${SCAFFOLD_TYPES.join('|')}> <name>`)
  process.exit(1)
}

const dir = join(process.cwd(), 'packages')
await scaffold({ type: type as typeof SCAFFOLD_TYPES[number], name, dir })

await writeFile(join(dir, name, '.eslintrc.cjs'), `module.exports = require('@myteam/eslint-config')\n`)
await writeFile(join(dir, name, '.prettierrc'), `"@myteam/prettier-config"\n`)

console.log(`Done. Run: pnpm --filter agentskit-${name} dev`)

#Testing your generated code

The scaffolded tests use Vitest with the same conventions as the core packages (vitest run, lint via tsc --noEmit). Wire them into your monorepo's CI right away — every new scaffold ships with its own contract test that typechecks + runs.

Explore nearby

✎ Edit this page on GitHub·Found a problem? Open an issue →·How to contribute →

On this page

Ask the docs
Ask anything about AgentsKit. Answers come from the docs corpus and cite their sources.