Development Workflow
Day-to-day commands and conventions for working on Polyant. Read Getting Started first if you have not yet run the project locally.
Prerequisites
- Node.js 22+ (LTS recommended)
- npm 10+ (ships with Node 22)
- Docker + Docker Compose (for PostgreSQL with pgvector)
- A POSIX-style shell (bash, zsh, fish)
Optional but recommended:
- An OpenAI or Anthropic API key (the engine needs at least one for LLM calls)
- An IDE with TypeScript support (VS Code, Cursor, etc.)
Setup
git clone https://github.com/polyant-ai/polyant.git
cd polyant
cp .env.example .env # then edit secrets
npm install # installs all workspaces
docker compose up -d # starts postgres on :5432
npm run db:migrate # creates schema + seeds demo-agentRun
All commands work from the monorepo root.
# Engine (NestJS) — OpenAI-compatible + management API on :4000
npm run dev
# alias:
npm run dev:engine
# Admin panel (Next.js) on :3000
npm run dev:webPer-workspace commands use -w:
npm run dev -w @polyant/engine
npm run build -w @polyant/webTest
npm run test:unit # vitest unit tests (engine)
npm run test:integration # database-backed integration tests
npm run test:functional # end-to-end pipeline tests
npm test # all of the above
npm run typecheck # tsc --noEmit on all workspaces
npm run lint # eslint on all workspacesCI runs typecheck + lint + test on every PR. Run them locally before
pushing.
Database
Drizzle ORM manages schema. Migrations live in
packages/engine/src/database/migrations/.
npm run db:generate # generate a migration from schema diff
npm run db:migrate # apply pending migrations
npm run db:studio # open Drizzle Studio GUINote:
npx drizzle-kit generatedoes not work in this repo because of an ESM incompatibility. Usenpm run db:generate(which calls drizzle-kit viatsx) or write incremental migrations by hand. See CLAUDE.md → “drizzle-kit with ESM” caveat.
Adding a new tool
Tools self-register at boot. The pattern is described in detail in CLAUDE.md → “Tool registry”.
- Create
packages/engine/src/agents/tools/<your-tool>.tool.ts. - Call
registerTool({ name, description, inputSchema, execute })at module top level. - Restart the engine —
loadAllTools()auto-discovers the file. - Enable the tool on an instance via the admin panel Tools tab (or
PATCH /api/instances/:slug/tools).
For canonical, in-tree examples see any *.tool.ts file under
packages/engine/src/agents/tools/
— every registered tool lives there and follows the same pattern.
Adding a new skill
Skills live in the skills + skill_versions DB tables — never on disk.
- Through the UI: admin panel → Skills library → New skill, then attach it to an instance via the Skills tab.
- Through the API:
POST /api/skillsthenPATCH /api/instances/:slug/skillsto enable it.
See Skill Frontmatter for the SKILL.md format (frontmatter + body).
Branching and commits
- Branch off
main:feat/<short-name>,fix/<short-name>, etc. - One logical change per commit.
- Conventional Commits format:
feat(engine): add Discord channel adapter fix(web): correct sidebar collapse on mobile docs: add deployment recipe for Fly.io - Sign off every commit with the DCO (
git commit -s). See CONTRIBUTING.md .
Pull request
- Push your branch and open a PR against
main. - The PR template asks for: summary, motivation, test plan.
- Make sure CI passes (
typecheck,lint,test). - Keep PRs focused — under ~400 lines of diff is easier to review.
- Address review feedback in new commits (no force-pushes during review).
- A maintainer will squash-merge once approved.
Where to look next
- Architecture — system design and pipeline overview.
- Glossary — terminology cheat sheet.
- CLAUDE.md — exhaustive conventions and caveats.
- CONTRIBUTING.md — DCO, code of conduct, review process.