Building with a coding agent
The workflow for writing an integration with a coding agent.
Coding agents such as Claude Code, Cursor or Codex can write most of a Connect package. The SDK CLI runs on your machine, so an agent can build, run and check its own work before you look at it.
Give the agent the right context
An agent writes a better integration when it reads the real contract instead of guessing from memory.
The SDK
@beetlio/connect is open source under the Apache-2.0 license, so the agent can read its full
source and type definitions in the GitHub repository and
the user guide. Once the SDK is installed, the type
definitions are also in node_modules/@beetlio/connect/dist/. For how Beetl runs a package, add
Authoring a sync,
Materialization, Authentication and
The sandbox.
The target API's documentation
Give the agent the provider's official reference for authentication, pagination, rate limits, filtering by last change, and how deleted records are reported. An agent left to infer an API from examples tends to miss the edge cases.
An example package
The SDK repository has runnable examples: a basic one with connection verification, an all-features one with OAuth, pagination and checkpoints, and a Wikidata one against a public API.
Plan before code
Ask the agent for a short written plan first and review it. A useful plan states:
- what the integration syncs and what it leaves out
- how authentication works, which permissions it needs, and how credentials are renewed
- for each sync: the source endpoint, a stable record ID to use as the primary key, full or incremental reads, what goes into the checkpoint, and how deletions are handled
- the pagination style and rate limits, with links to the docs that support each choice
The plan is cheap to correct. Sync keys, record schemas and primary keys are not: they become part of the package's contract once it is installed.
A loop that works
Scaffold
Have the agent create package.json with "type": "module" and a files allowlist, install the
SDK with npm install --save-dev @beetlio/connect, and create integration.ts. The
quickstart is a good template.
Implement authentication and one sync
Use the SDK's auth helpers in connection.auth and add a verify function that makes one small
authenticated request. Then write one representative sync and leave the others until it works.
Run it locally
configure asks for credentials and needs an interactive terminal, so run it yourself:
npx beetl-connect configure . ordersThe agent can then run the sync on its own and read the output:
npx beetl-connect sync . orders --output orders.ndjsonFor syncs that take no credentials, the agent can pass settings with --inputs and configure
without prompts. Both commands exit with a non-zero status on failure.
Check the records
The SDK validates every record against the sync's schema, so a passing run proves the shape. Ask the agent to check what validation does not cover: the record count matches what the API reports, primary keys are unique across the whole output, and fields that should be filled are not empty. Compare a few records with the provider's own UI yourself. For a Merge sync, the output file holds batches of records and deletions rather than one record per line.
Add incremental checkpoints
Declare a checkpoint and save the position after each batch. Local runs store checkpoints under
.beetl/state/, so running the same sync twice shows whether the second run reads only what
changed. Delete the state file, or pass --state with a new path, to start from scratch.
Add the remaining syncs, then pack
Repeat the loop for each sync. Finish with npx beetl-connect pack . --output acme.tgz and read
the printed file list. See Pack and upload.
A starting prompt
Adapt this to your agent and API:
Build a Beetl Connect integration for the Acme Orders API using @beetlio/connect.
Read first:
- The SDK user guide: https://beetlio.github.io/connect/
- The SDK source and examples: https://github.com/beetlio/connect
- The Acme API reference: <link>
Write a plan before any code: syncs, primary keys, auth, pagination,
incremental strategy, deletions, rate limits, with doc links. Wait for my review.
Then implement auth with verify() and the "orders" sync only. I will run
`npx beetl-connect configure . orders` myself. You run
`npx beetl-connect sync . orders --output orders.ndjson` and report the record
count, duplicate primary keys and empty required fields.
Never print, log or commit credentials. Only read from the API.Keep credentials away from the agent
Credentials saved by configure live in your operating system's user configuration folder, not in
the project. They are readable by your user account but not encrypted, so an agent with full disk
access could read them. Use a test account with the narrowest permissions the API allows, and keep
any local secrets files out of version control. pack refuses .env* files and the .beetl
folder in any case.
Review before you upload
Read the code yourself before a TenantAdmin uploads it. Check that:
- credentials are declared in
connection.auth, never as ordinary inputs, custom secret fields are marked withsecret(), andverifyfails on bad access - pagination reaches the last page, and API errors fail the run instead of returning an empty result
- every primary key is stable, unique, required and never null
- each batch carries the checkpoint to resume after it, and a repeated run does not duplicate records
- the integration only reads from the provider
- nothing logs tokens, request headers or full responses, and
ctx.logis used for messages - the
filesallowlist ships only what the package needs
Run the whole loop again after any change to the code or its dependencies. A result from an earlier version says nothing about the new package.
Last updated on