The @tangogroup/forge-sdk package provides a typed TypeScript client for the full Forge Platform API. It uses native fetch with zero runtime dependencies and works in Node.js, browsers, and edge runtimes.
📦 Installation
npm install @tangogroup/forge-sdk
🚀 Quick Start
import { ForgeClient , ForgeApiError } from "@tangogroup/forge-sdk" ;
const forge = new ForgeClient ({
baseUrl: "https://forge.gloo.ai" ,
apiKey: process . env . FORGE_API_KEY ! ,
});
// List all agents
const { data : agents , meta } = await forge . listAgents ();
console . log ( `Found ${ agents . length } agents (requestId: ${ meta . requestId } )` );
// Get a specific agent
const { data : agent } = await forge . getAgent ( "agent_abc123" );
console . log ( `Agent: ${ agent . name } ( ${ agent . tier } )` );
⚙️ Initialization
The ForgeClient constructor accepts a base URL and an API key.
import { ForgeClient } from "@tangogroup/forge-sdk" ;
const forge = new ForgeClient ({
baseUrl: "https://forge.gloo.ai" ,
apiKey: "forge_sk_abc123..." ,
});
The root URL of your Forge deployment. Do not include a trailing slash.
A Forge API key with the scopes required for the methods you intend to call.
Never hardcode API keys in source code. Use environment variables or a secrets manager.
Every method returns a Promise that resolves to a response object with data and meta fields.
const response = await forge . listAgents ();
// response.data — the payload (Agent[] in this case)
// response.meta — { requestId: string, hasMore?: boolean, nextCursor?: string | null }
For list endpoints, meta.hasMore indicates whether more results are available, and meta.nextCursor provides the cursor for the next page.
📋 Client Methods
Agents (v1)
V1 agent endpoints return the gateway-layer shape — useful when you need deployment status, gateway bindings, and runtime capabilities. For the definition-layer shape (purpose, governance, version), use the V2 methods.
listAgents
List all agents registered on the platform.
// List all agents
const { data : agents } = await forge . listAgents ();
// Filter by gateway
const { data : gatewayAgents } = await forge . listAgents ({ gatewayId: "gw_openclaw" });
Optional. Filter to agents deployed on a specific gateway.
getAgent
Get detailed information about a specific agent.
const { data : agent } = await forge . getAgent ( "agent_abc123" );
console . log ( agent . name ); // "Code Reviewer"
console . log ( agent . tier ); // "standard"
console . log ( agent . skills ); // ["code-review", "testing"]
console . log ( agent . capabilities ); // { streaming: true, ... }
transitionAgentStage
Transition an agent’s lifecycle stage. Valid stages: draft, active, suspended, archived.
const { data : result } = await forge . transitionAgentStage (
"agent_abc123" ,
"active" ,
"Passed review and ready for production"
);
console . log ( result . status ); // "completed" or "pending_approval"
console . log ( result . from ); // "draft"
console . log ( result . to ); // "active"
If governance policies require approval for the transition, the status will be "pending_approval" and the response will include an approvalId.
getAgentLifecycleHistory
Get the lifecycle transition history for an agent.
const { data : history } = await forge . getAgentLifecycleHistory ( "agent_abc123" , 10 );
console . log ( history . currentStage ); // "active"
for ( const t of history . transitions ) {
console . log ( ` ${ t . from } -> ${ t . to } ( ${ t . event } ) by ${ t . actor } ` );
}
Agents (v2)
V2 agent endpoints return the definition-layer shape with richer metadata.
listAgentsV2
const { data : agents } = await forge . listAgentsV2 ();
getAgentV2
const { data : agent } = await forge . getAgentV2 ( "agent_abc123" );
console . log ( agent . purpose );
console . log ( agent . version );
console . log ( agent . governance );
deployAgent
Deploy an agent to a specific gateway.
const { data : result } = await forge . deployAgent (
"agent_abc123" ,
"gw_openclaw" ,
{ model: "anthropic/claude-sonnet-4-20250514" } // optional overrides
);
console . log ( result . deploymentId );
undeployAgent
Remove an agent deployment from a gateway.
const { data : result } = await forge . undeployAgent ( "agent_abc123" , "gw_openclaw" );
console . log ( result . status ); // "undeployed"
Runs
listRuns
List workflow runs with optional filters.
// List recent runs
const { data : runs } = await forge . listRuns ();
// Filter by type with a limit
const { data : workflowRuns } = await forge . listRuns ({
runType: "workflow" ,
limit: 10 ,
});
for ( const run of workflowRuns ) {
console . log ( ` ${ run . id } : ${ run . status } ( ${ run . totalTokens ?? 0 } tokens)` );
}
Optional. Filter by run type.
Optional. Maximum results to return. Range: 1-100. Default: 25.
getRun
Get detailed information about a specific run, including its steps.
const { data : run } = await forge . getRun ( "run_xyz789" );
console . log ( `Status: ${ run . status } ` );
console . log ( `Steps: ${ run . steps . length } ` );
for ( const step of run . steps ) {
console . log ( ` ${ step . stepId } : ${ step . status } ( ${ step . totalTokens ?? 0 } tokens)` );
}
Events
listEvents
Query platform events with compound filters and cursor-based pagination.
const { data : events , meta } = await forge . listEvents ({
since: "2026-04-01T00:00:00Z" ,
category: [ "lifecycle" , "error" ],
severity: [ "error" , "critical" ],
limit: 50 ,
});
for ( const event of events ) {
console . log ( `[ ${ event . severity } ] ${ event . displayLabel } ` );
}
// Paginate
if ( meta . hasMore && meta . nextCursor ) {
const { data : nextPage } = await forge . listEvents ({
since: "2026-04-01T00:00:00Z" ,
cursor: meta . nextCursor ,
});
}
getEventSummary
Get aggregated event counts broken down by category, severity, and source.
const { data : summary } = await forge . getEventSummary ({
since: "2026-04-01T00:00:00Z" ,
agentId: "agent_abc123" , // optional scope
});
console . log ( `Total events: ${ summary . total } ` );
console . log ( `By severity:` , summary . bySeverity );
console . log ( `By category:` , summary . byCategory );
Cost
listCost
Query cost aggregates with optional filters.
const { data : cost } = await forge . listCost ();
Keys
createKey
Create a new API key with specific scopes.
const { data : key } = await forge . createKey ({
scopes: [ "agents:read" , "runs:read" ],
label: "CI pipeline" ,
expiresAt: Date . now () + 30 * 24 * 60 * 60 * 1000 , // 30 days
});
The full API key value is only returned once in the creation response. Store it securely — it cannot be retrieved again.
listKeys
List all API keys for the current interface.
const { data : keys } = await forge . listKeys ();
for ( const key of keys ) {
console . log ( ` ${ key . label } : ${ key . scopes . join ( ", " ) } ` );
}
revokeKey
Revoke an API key by ID. Revoked keys immediately stop working.
await forge . revokeKey ( "key_abc123" );
Skills
listSkills
List all skills in the skill catalog.
const { data : skills } = await forge . listSkills ();
for ( const skill of skills ) {
console . log ( ` ${ skill . name } ( ${ skill . status } ) - ${ skill . description } ` );
}
getSkill
Get a specific skill by ID.
const { data : skill } = await forge . getSkill ( "skill_code_review" );
Models
listModels
List all models in the model catalog.
const { data : models } = await forge . listModels ();
for ( const model of models ) {
console . log ( ` ${ model . displayName } ( ${ model . provider } ) - ctx: ${ model . contextWindow } ` );
}
getModel
Get a specific model by ID.
const { data : model } = await forge . getModel ( "anthropic/claude-sonnet-4-20250514" );
Workflows
listWorkflows
List all workflow definitions.
const { data : workflows } = await forge . listWorkflows ();
for ( const wf of workflows ) {
console . log ( ` ${ wf . name } v ${ wf . currentVersion } ( ${ wf . status } )` );
}
getWorkflow
Get a specific workflow by ID or name.
const { data : workflow } = await forge . getWorkflow ( "vendor-onboarding" );
Budgets
getBudgetStatus
Get budget status across all scopes.
const { data : budgets } = await forge . getBudgetStatus ();
for ( const budget of budgets ) {
console . log (
` ${ budget . scope } : $ ${ ( budget . usedCents / 100 ). toFixed ( 2 ) } / $ ${ ( budget . budgetCents / 100 ). toFixed ( 2 ) } ( ${ budget . percentUsed . toFixed ( 1 ) } %)`
);
}
Evals
listEvals
List evaluation sets.
const { data : evals } = await forge . listEvals ();
getEval
Get an evaluation set by ID.
const { data : evalSet } = await forge . getEval ( "eval_abc123" );
listEvalRuns
List runs for a specific evaluation set.
const { data : runs } = await forge . listEvalRuns ( "eval_abc123" );
❌ Error Handling
All client methods throw ForgeApiError when the API returns a non-2xx response. The error object includes the HTTP status, the machine-readable error code, the response body, and the request metadata.
import { ForgeClient , ForgeApiError } from "@tangogroup/forge-sdk" ;
const forge = new ForgeClient ({
baseUrl: "https://forge.gloo.ai" ,
apiKey: process . env . FORGE_API_KEY ! ,
});
try {
const { data : agent } = await forge . getAgent ( "nonexistent_id" );
} catch ( error ) {
if ( error instanceof ForgeApiError ) {
console . error ( `Status: ${ error . status } ` ); // 404
console . error ( `Code: ${ error . code } ` ); // "not_found"
console . error ( `Message: ${ error . message } ` ); // "Agent with ID '...' does not exist."
console . error ( `Request ID: ${ error . meta ?. requestId } ` );
}
}
ForgeApiError Properties
Property Type Description statusnumberHTTP status code (400, 401, 403, 404, 500) codestringMachine-readable error code (unauthorized, forbidden, not_found, bad_request, internal_error) messagestringHuman-readable error description metaobject | nullResponse metadata including requestId
Common Error Patterns
try {
await forge . deployAgent ( agentId , gatewayId );
} catch ( error ) {
if ( error instanceof ForgeApiError ) {
switch ( error . code ) {
case "unauthorized" :
// API key is missing or revoked
break ;
case "forbidden" :
// Key lacks agents:write scope
break ;
case "not_found" :
// Agent or gateway does not exist
break ;
case "bad_request" :
// Invalid request parameters
break ;
case "internal_error" :
// Server error -- retry or report with requestId
break ;
}
}
}
🏷️ TypeScript Types
The SDK exports all response types for use in your application code.
import type {
Agent ,
Run ,
RunDetail ,
RunStep ,
HealthStatus ,
PlatformEvent ,
EventSummary ,
SkillSummary ,
ModelSummary ,
WorkflowSummary ,
BudgetStatus ,
LifecycleTransitionResult ,
LifecycleHistory ,
} from "@tangogroup/forge-sdk" ;
🚀 Next Steps
API Reference Full endpoint documentation with request/response schemas.
MCP Server Give AI agents direct access to Forge through the Model Context Protocol.