> ## Documentation Index
> Fetch the complete documentation index at: https://docs.erstan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK quickstart

> Install the beta SDK in a Node.js project and run a hosted Erstan Agent.

`@erstan/sdk` is the JavaScript ESM client for Erstan, with TypeScript declarations.
Use Node.js 22 or later. Agents execute in Erstan with their saved connections,
permissions, and approval policies; the SDK is not an offline Agent engine.
You do not need a CLI, repository template, test runner, or backend checkout.

<Warning>
  The SDK is currently an unpublished private beta (`0.1.0-beta.1`). It is not
  available from the public npm registry. Beta users need a reviewed package
  tarball from Erstan or access to the private SDK repository. Publishing these
  docs does not publish the package or enable authoring for your workspace.
</Warning>

## Install the beta package

Install the reviewed archive into your existing Node.js project, using its
actual local path:

```bash theme={null}
npm install ./erstan-sdk-0.1.0-beta.1.tgz
```

Developers with access to the [private SDK repository](https://github.com/erstanai/erstan-agent-toolkit)
can follow its [package build instructions](https://github.com/erstanai/erstan-agent-toolkit/blob/main/packages/sdk/README.md)
to produce the archive. That repository and the sample links require beta
access; without it, use the public [REST quickstart](/developers/quickstart).

The SDK and the [coding-agent plugin](/developers/connect-coding-agent) are
independent. The plugin uses host-managed OAuth; the SDK uses a scoped API key
in trusted application code. Neither installs or updates the other.

## Configure a run

Create a key using [API Keys](/developers/api-keys). Starting and observing a run
requires `agents:run` and `runs:read`; discovery also requires `agents:list`.
The key creator must retain access to the Agent.

Configure these values in your trusted local or server environment:

| Variable                 | Value                                                                                                       |
| ------------------------ | ----------------------------------------------------------------------------------------------------------- |
| `ERSTAN_API_KEY`         | The scoped key; never commit it or expose it in browser code.                                               |
| `ERSTAN_API_BASE`        | `https://api.erstan.com` for production or `https://api-qa.erstan.com` for QA. Use an origin without `/v1`. |
| `ERSTAN_AGENT_ID`        | An explicitly selected published Agent.                                                                     |
| `ERSTAN_LANE_ID`         | A chat lane from that Agent's published lane details.                                                       |
| `ERSTAN_IDEMPOTENCY_KEY` | A stored key for this one logical launch; reuse only with identical intent on retry.                        |

Use the same SDK package for either environment, with that environment's
credential and Agent IDs. Do not fall back from QA to production when a request
fails. Keep secrets and sensitive results out of Git and unreviewed CI jobs.

## Run a published Agent

Save this as `run.mjs`. The example deliberately selects a chat lane; structured
lanes require an `input` object matching their own advertised schema.

```js theme={null}
import { ErstanClient, ErstanError } from '@erstan/sdk';

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name} before running this example.`);
  return value;
}

const client = new ErstanClient({
  apiKey: required('ERSTAN_API_KEY'),
  apiBase: required('ERSTAN_API_BASE'),
});

try {
  const result = await client.agents.runAndWait(required('ERSTAN_AGENT_ID'), {
    laneId: required('ERSTAN_LANE_ID'),
    input: { message: 'Hello from my application.' },
    idempotencyKey: required('ERSTAN_IDEMPOTENCY_KEY'),
  }, { waitTimeoutMs: 300_000 });

  console.log('Run:', result.run.runId, 'Outcome:', result.reason);
  if (result.reason === 'completed') {
    console.log(result.run.finalResponse);
  }
  // An interaction or other pause needs application/user handling, not a new run.
} catch (error) {
  if (error instanceof ErstanError && error.runId) {
    console.error('Resume observation of this accepted run:', error.runId);
  }
  throw error;
}
```

When you intend a live execution, run:

```bash theme={null}
node run.mjs
```

<Warning>
  A run can incur costs and external effects. Importing the SDK does not start
  work, but calling `run` or `runAndWait` does. The SDK never answers approval or
  user-input waits automatically. Do not start a replacement run just because
  observation timed out: the original run may still be executing.
</Warning>

`runAndWait` returns `completed`, `failed`, `cancelled`, `interaction`, `waiting`,
or `unknown_status` as its `reason`. An Agent failure is a result, not necessarily
an HTTP exception. Validate the shape of `finalResponse` before using it in
application logic. Use `runs.wait(runId)` to resume observation with the exact
key that started the run. A rotated or replacement key cannot read its runs.

Continue with the [SDK reference](/developers/sdk-reference) for methods,
configuration, authoring, and recovery, or [optional examples](/developers/sdk-examples)
for human review and keeping Agent/Skill files in your own repository.
