typescript-support-agent
A Node.js example that defines three support-team tools with platools.tool() + Zod, runs them in a bare Node process, and wires platools doctor into the build.
What’s in the box
examples/typescript-support-agent/├── README.md├── package.json├── tsconfig.json├── .env.example├── .gitignore└── src/ ├── platools.ts # `new Platools({...})` instance ├── schemas.ts # shared Zod schemas ├── tools.ts # `platools.tool(...)` registrations ├── registry.ts # doctor-friendly barrel (re-exports `platools`) └── main.ts # bootstrap + platools.connect()The registry.ts barrel exists so platools doctor ./dist/registry.js can find every registered tool with one import. It side-effect imports ./tools.js (so the platools.tool(...) calls actually run) and re-exports the platools instance the doctor walks. Without that barrel, importing only platools.js would walk an empty registry and miss every tool - see Examples -> workspace wiring for the rationale.
The tools
src/tools.ts registers three tools on the shared instance:
list_tickets({ customerId, status?, limit })->Ticket[]-auth="user",roles=["support"]. Lists support tickets for a customer.reply_to_ticket({ ticketId, body })->Reply-auth="user",roles=["support"]. Posts a reply to an open ticket.escalate_ticket({ ticketId, priority, reason })->Ticket-auth="admin",roles=["support", "team-lead"]. Raises a ticket’s priority.
Every input is a Zod object with .describe() descriptions on every field. Every output is a named Zod schema imported from src/schemas.ts so the same shapes can be reused in the rest of the app.
Running it
cd examples/typescript-support-agent
# One-time setupcp .env.example .envpnpm install
# Typecheck - must be greenpnpm typecheck
# Compile to dist/pnpm build
# Static analysis - ship gate. Runs against the built barrel.pnpm doctor
# Run the Node host (skips connect() if PLATOS_URL/PLATOS_SECRET unset)pnpm startWhat to learn from it
- Zod schemas are the source of truth.
src/schemas.tsexports every reusable shape; both the tool registrations and the fake in-memory ticket store import from the same module. .describe()on every field. Doctor flags parameters without descriptions; reusable Zod schemas make it easy to write the description once and share it.auth+rolesmap directly to the Python SDK. Reading a tool’s registration insrc/tools.tsnext to the Python example’s equivalent, the only differences are Zod vs. Pydantic syntax - the semantics line up exactly.- No decorators. TC39 decorators are still in flux; the SDK uses plain
platools.tool(options, handler)for parity across TS versions and bundlers. - Workspace-linked SDK.
package.jsonreferences@platools/sdkviaworkspace:*so the example always builds against the source-of-truth SDK in the monorepo.
Source: examples/typescript-support-agent/
Next steps
- python-billing-agent - the same pattern in Python.
- local-dev-loop - run tools locally via
platools serve. - TypeScript SDK - full reference for the tool factory, schemas, and client.