@phaseo/agent-sdk when your application needs more than one-shot text generation:
- multi-step tool loops
- local runtime tools
- resumable runs from SDK-returned state
- explicit human approval pauses
- typed final outputs
- gateway-backed model turns through the existing TypeScript SDK
State model
The Agent SDK does not persist runs into any Phaseo-hosted service.run()returns the full state needed to continue later.- If your application wants resumability across requests or process restarts, persist that returned state in your own application store.
continueRun()accepts that prior run state directly.
Install
What the SDK ships
createAgent()defineTool()createGatewayAgentClient()continueRun()for continuing from previously returned run statestream()andcontinueStream()for incremental, replayable results- stop-condition helpers such as
stepCountIs(),maxCost(), andhasToolCall()
First agent
Mental model
The runtime loop does four things:- sends the current message state to the model client
- executes any returned local tool calls
- appends tool results into the next turn
- returns the updated run state after each completed step boundary
Core primitives
createAgent()
Use createAgent() to define:
- one stable
id - instructions
- one model or preset
- one small tool list
- optional output parsing
- optional human review rules
- optional retry and tool-execution controls
defineTool()
Define local runtime tools with:
iddescription- optional JSON
parameters - optional
timeoutMs inputSchemaandoutputSchemaruntime validatorsexecute(),execute: false, or human-in-the-loop callbacksrequireApproval,onError,nextTurnParams, and progress events
context.signal, marks the run as failed, and rethrows the timeout error.
Schemas can be a function or any object exposing parse() or safeParse(). Invalid model arguments and invalid tool results fail before they cross the tool boundary.
Approval, HITL, and manual tools
Gate a side-effecting tool per call:run.pause.pendingToolCalls. Resume by exact call ID so concurrent calls cannot be confused:
execute: false for work performed by your application and provide its result through toolOutputs. For an interactive tool, return null from onToolCalled; after continuation, onResponseReceived can validate or transform the supplied human response.
Progress-producing tools
An async generator can publish preliminary results and return one final result:tool.preliminary_result events and in the step’s preliminaryResults.
Streaming results
stream() starts the same state machine with a streaming model client. Its consumers are replayable, so UI, telemetry, and persistence code can read concurrently:
getReasoningStream(), getItemsStream(), getToolStream(), or getFullStream() for more specific consumers. cancel() aborts the run.
Render typed run items
getItemsStream() yields AgentItem<TOutput>, a discriminated union that is safe to switch on:
completed.items after either run() or stream(). Provider output is normalized into message, reasoning, tool-call, tool-result, error, and final-output items. Provider-specific fields remain available through rawProviderItem on normalized provider items.
Stop conditions and dynamic turns
Stop conditions compose as an array; the first matching condition records its reason and returns astopped run:
context.setContext() and override the immediately following turn with nextTurnParams.
createGatewayAgentClient()
Use the gateway-backed adapter when model turns should execute through Phaseo Gateway.
It can carry gateway-native controls such as:
responseFormatpluginsgatewayToolstoolChoicewebSearchOptionsproviderOptionspromptCacheKeyincludeMeta
Application-owned persistence
If your application needs resumability, persist the returnedAgentRunResult directly or provide a state accessor with asynchronous load(runId) and save(result) methods. A continued run can then use runId without carrying the serialized record through every layer.
The SDK intentionally does not ship persistence adapters or a hosted state backend.
That means you can:
- keep one-shot runs entirely in-process
- serialize paused or incomplete runs into your own application records
- reload that saved run state and pass it back to
continueRun()later
Human review and continuation
UsehumanReview when a run should checkpoint and wait for approval:
Typed outputs
UseparseOutput when your app wants a typed final value:
Runtime controls
Model retries
UsemodelRetry when transient model failures should retry before the run is persisted as failed:
maxRetries counts extra attempts after the first model request.
The persisted step record stores the final retry count as modelAttempts.
Concurrent local tools
If one model turn can safely call several independent tools, settoolExecution.toolConcurrency:
Preset-driven routing
Usepreset when routing, prompt, or parameter defaults should stay managed in the dashboard instead of being hard-coded in app code:
Event hooks
UseonEvent when your application wants lifecycle hooks for logs, telemetry, or internal workflows.
Current events include:
run.startedrun.resumedstep.startedstep.completedstep.failedstep.cancelledmodel.requestedmodel.completedmodel.failedtool.startedtool.completedtool.failedcheckpoint.savedrun.waiting_for_humanrun.cancelledrun.completedrun.failed
step.completed after the checkpointed step has been persisted.
Error handling
Gateway failures are rethrown asAgentGatewayError:
errorDetails.
Included examples
The package currently ships these examples:examples/research-brief-agent.tsexamples/support-triage-agent.tsexamples/coding-review-agent.tsexamples/parallel-tool-agent.ts
Current scope
The SDK is intentionally focused on application-building primitives:- local or app-owned checkpoint persistence
- gateway-backed model turns
- local tools
- resumable agent loops
- per-step normalized token usage, cost, warnings, finish reasons, and tool results