TypeScript SDK

phoson-ts

Official TypeScript client for the Phoson Core API. Fully typed with exported interfaces, streaming via native async iterators, and multi-provider support.

$npm install phoson-ts
Node.js 18+TypeScript 5+Async iteratorsFull type exportsESM + CJS

Installation

Install via npm, yarn, or pnpm.

bash
npm install phoson-ts
bash
yarn add phoson-ts
bash
pnpm add phoson-ts

Quick Start

Create a client, spin up an agent, start a conversation, and stream a response.

main.ts
import { PhosonClient } from "phoson-ts";

const client = new PhosonClient({ apiKey: "pk_...", baseUrl: "https://api.phoson.ai" });

// 1. Create an agent
const agent = await client.agents.create({
  name: "My Assistant",
  description: "A helpful assistant",
  memory_type: "persistent",
});

// 2. Start a conversation
const conv = await client.conversations.create({ agent_id: agent.id });

// 3. Stream a response
for await (const event of client.messages.stream(conv.id, "Hello, how are you?")) {
  if (event.type === "token") {
    process.stdout.write(event.content);
  } else if (event.type === "run_done") {
    console.log(`\n\nRun ID: ${event.run_id}`);
  }
}

Authentication

All requests are authenticated with an API key sent as a Bearer token. Get your key from the dashboard settings.

typescript
import { PhosonClient } from "phoson-ts";

const client = new PhosonClient({ apiKey: "pk_your_api_key_here" });
Security: Never hardcode API keys in source code. Use environment variables: new PhosonClient({ apiKey: process.env.PHOSON_API_KEY! })

PhosonClient

The top-level client that exposes all resource managers.

typescript
new PhosonClient({ apiKey: string, baseUrl?: string })

baseUrl defaults to https://api.phoson.ai.

Agents

Agents are the core entities in Phoson. Each agent has its own memory, identity, and optional MCP tool integrations. Access via client.agents.

create

typescript
const agent = await client.agents.create({
  name: "My Agent",
  description: "What this agent does",
  memory_type: "persistent", // "persistent" | "semantic", default "persistent"
});

list

typescript
const agents = await client.agents.list();

get

typescript
const agent = await client.agents.get(agentId);

update

typescript
const agent = await client.agents.update(agentId, { name: "New name" });

delete

typescript
await client.agents.delete(agentId);

attachMcp / detachMcp

Attach or detach an MCP server from an agent to give it tool-use capabilities.

typescript
await client.agents.attachMcp(agentId, mcpId);
await client.agents.detachMcp(agentId, mcpId);

Conversations

A conversation is a thread of messages between a user and an agent. Access via client.conversations.

create

typescript
const conv = await client.conversations.create({
  agent_id: agent.id,
  title: "My conversation",  // optional, default "New Conversation"
  thread_id: "custom-id",    // optional
});

list

typescript
const convs = await client.conversations.list();
const convs = await client.conversations.list(agentId); // filter by agent

get

typescript
const conv = await client.conversations.get(conversationId);

update

typescript
const conv = await client.conversations.update(conversationId, { title: "New title" });

delete

typescript
await client.conversations.delete(conversationId);

Messages

Send messages to a conversation and receive AI responses. Access via client.messages.

stream

Sends a message and returns an AsyncIterableIterator<StreamEvent>. Recommended for interactive applications.

stream.ts
for await (const event of client.messages.stream(
  conversationId,
  "Your message here",
  {
    model: "claude-sonnet-4-6",    // optional
    provider: "anthropic",         // "anthropic" | "openai" | "openrouter"
    temperature: 0.7,              // optional
    max_tokens: 4096,              // optional
    reasoning_effort: "medium",    // "low" | "medium" | "high", optional
  },
)) {
  switch (event.type) {
    case "token":
      process.stdout.write(event.content);
      break;
    case "reasoning":
      console.log(`[thinking] ${event.content}`);
      break;
    case "tool_start":
      console.log(`→ Running tool: ${event.tool}`);
      break;
    case "tool_end":
      console.log(`← Tool result: ${event.result}`);
      break;
    case "run_done":
      console.log(`\nDone. Run ID: ${event.run_id}`);
      break;
    case "error":
      console.error(`Error: ${event.message}`);
      break;
  }
}

send

Non-streaming version. Waits for the full response before returning.

typescript
const message = await client.messages.send(
  conversationId,
  "Your message here",
  { model: "claude-sonnet-4-6", provider: "anthropic" },
);
console.log(message.content);

list

Retrieves the full message history of a conversation.

typescript
const messages = await client.messages.list(conversationId);
for (const msg of messages) {
  console.log(`[${msg.role}]`, msg.content);
}

Stream Events

All event types are exported and fully typed. Import them for type-safe event handling.

typescript
import type { StreamEvent, TokenEvent, RunDoneEvent } from "phoson-ts";

token

content: string

reasoning

content: string

tool_start

tool: string, input: Record<string, unknown>, tool_call_id: string

tool_end

tool: string, result: string, tool_call_id: string

run_done

content: string, run_id: string

error

message: string

Error Handling

The SDK throws PhosonAPIError for all API errors, exposing statusCode and detail.

typescript
import { PhosonAPIError } from "phoson-ts";

try {
  await client.agents.get("non-existent-id");
} catch (e) {
  if (e instanceof PhosonAPIError) {
    console.log(e.statusCode); // 404
    console.log(e.detail);     // "Agent not found"
  }
}