Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions src/resources/agents/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ import {
import { APIPromise } from '../../core/api-promise';
import { RequestOptions } from '../../internal/request-options';
import { path } from '../../internal/utils/path';
import { sleep } from '../../internal/utils/sleep';

export class Agents extends APIResource {
apiKeys: APIKeysAPI.APIKeys = new APIKeysAPI.APIKeys(this._client);
Expand Down Expand Up @@ -266,6 +267,78 @@ export class Agents extends APIResource {
...options,
});
}

/**
* Polls the agent until its deployment reaches STATUS_RUNNING (or fails/timeout).
*
* This is useful after creating or updating an agent which triggers a deployment.
*
* @example
* ```ts
* const agent = await client.agents.waitForDeployment('123e4567-e89b-12d3-a456-426614174000');
* ```
*/
async waitForDeployment(
uuid: string,
waitOptions: Agents.WaitForDeploymentOptions = {},
options?: RequestOptions,
): Promise<AgentRetrieveResponse> {
const intervalMs = waitOptions.intervalMs ?? 2000;
const timeoutMs = waitOptions.timeoutMs ?? 5 * 60 * 1000; // 5 minutes default
const throwOnFailure = waitOptions.throwOnFailure ?? true;
const start = Date.now();

// loop until running, failed, or timeout
for (;;) {
const resp = await this.retrieve(uuid, options);
const status = resp.agent?.deployment?.status;

if (status === 'STATUS_RUNNING') return resp;

if (
status === 'STATUS_FAILED' ||
status === 'STATUS_UNDEPLOYMENT_FAILED' ||
status === 'STATUS_DELETED'
) {
if (throwOnFailure) {
const details = JSON.stringify(resp.agent?.deployment ?? {}, null, 2);
throw new Error(
`Agent deployment ended in a failure state: ${status}. Deployment details: ${details}`,
);
}
return resp;
}

if (Date.now() - start >= timeoutMs) {
throw new Error(
`Timed out waiting for agent deployment to reach STATUS_RUNNING after ${Math.round(timeoutMs / 1000)}s (last status: ${status ?? 'unknown'}).`,
);
}

await sleep(intervalMs);
}
}

/**
* Convenience helper to create an agent and wait until its deployment is running.
*
* @example
* ```ts
* const agent = await client.agents.createAndWait({ name: 'My Agent', model_uuid: '...' });
* ```
*/
async createAndWait(
body: AgentCreateParams | null | undefined = {},
waitOptions: Agents.WaitForDeploymentOptions = {},
options?: RequestOptions,
): Promise<AgentRetrieveResponse> {
const created = await this.create(body, options);
const newUUID = created.agent?.uuid;
if (!newUUID) {
throw new Error('Agent creation response did not include a uuid.');
}
return this.waitForDeployment(newUUID, waitOptions, options);
}
}

/**
Expand Down Expand Up @@ -1868,3 +1941,24 @@ export declare namespace Agents {
type RouteAddParams as RouteAddParams,
};
}

// Additional helper types for the Agents class
export declare namespace Agents {
export interface WaitForDeploymentOptions {
/**
* Polling interval in milliseconds. Default: 2000 (2 seconds)
*/
intervalMs?: number;

/**
* Maximum time to wait in milliseconds before timing out. Default: 300000 (5 minutes)
*/
timeoutMs?: number;

/**
* If true (default), throw an error when the deployment reaches a failure state.
* If false, return the last retrieved agent response instead.
*/
throwOnFailure?: boolean;
}
}