subconscious-dev
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuilding with Subconscious Platform
使用Subconscious平台构建应用
Subconscious is a platform for running AI agents with external tool use and long-horizon reasoning. Key differentiator: You kick off an agent with a single API call—define goals and tools, Subconscious handles orchestration, context management, and multi-hop reasoning automatically. No multi-agent frameworks needed.
Subconscious是一个支持外部工具调用和长周期推理的AI Agent运行平台。核心优势:只需一次API调用即可启动Agent——定义目标和工具后,Subconscious会自动处理编排、上下文管理和多跳推理,无需使用多Agent框架。
Quick Start
快速开始
Use the native Subconscious SDK (recommended approach):
使用原生Subconscious SDK(推荐方式):
Python
Python
python
from subconscious import Subconscious
client = Subconscious(api_key="your-api-key") # Get from https://subconscious.dev/platform
run = client.run(
engine="tim-gpt",
input={
"instructions": "Research quantum computing breakthroughs in 2025",
"tools": [] # Optional: see Tools section below
},
options={"await_completion": True}
)python
from subconscious import Subconscious
client = Subconscious(api_key="your-api-key") # Get from https://subconscious.dev/platform
run = client.run(
engine="tim-gpt",
input={
"instructions": "Research quantum computing breakthroughs in 2025",
"tools": [] # Optional: see Tools section below
},
options={"await_completion": True}
)Extract the answer for display
Extract the answer for display
answer = run.result.answer # Clean text response
print(answer)
undefinedanswer = run.result.answer # Clean text response
print(answer)
undefinedNode.js/TypeScript
Node.js/TypeScript
typescript
import { Subconscious } from "subconscious";
const client = new Subconscious({
apiKey: process.env.SUBCONSCIOUS_API_KEY!,
});
const run = await client.run({
engine: "tim-gpt",
input: {
instructions: "Research quantum computing breakthroughs in 2025",
tools: [], // Optional: see Tools section below
},
options: { awaitCompletion: true },
});
// Extract the answer for display
const answer = run.result?.answer; // Clean text response
console.log(answer);typescript
import { Subconscious } from "subconscious";
const client = new Subconscious({
apiKey: process.env.SUBCONSCIOUS_API_KEY!,
});
const run = await client.run({
engine: "tim-gpt",
input: {
instructions: "Research quantum computing breakthroughs in 2025",
tools: [], // Optional: see Tools section below
},
options: { awaitCompletion: true },
});
// Extract the answer for display
const answer = run.result?.answer; // Clean text response
console.log(answer);Response Structure
响应结构
Critical: The Subconscious SDK returns a different structure than OpenAI:
typescript
{
runId: "run_abc123...",
status: "succeeded",
result: {
answer: "The clean text response for display", // ← Use this for chat UIs
reasoning: [ // Optional: step-by-step reasoning
{
title: "Step 1",
thought: "I need to search for...",
conclusion: "Found relevant information"
}
]
},
usage: {
inputTokens: 1234,
outputTokens: 567,
durationMs: 45000
}
}For chat UIs, always use - this is the clean text response. The field contains internal reasoning steps (useful for debugging but not for display).
run.result?.answerreasoning重点提示:Subconscious SDK返回的结构与OpenAI不同:
typescript
{
runId: "run_abc123...",
status: "succeeded",
result: {
answer: "The clean text response for display", // ← Use this for chat UIs
reasoning: [ // Optional: step-by-step reasoning
{
title: "Step 1",
thought: "I need to search for...",
conclusion: "Found relevant information"
}
]
},
usage: {
inputTokens: 1234,
outputTokens: 567,
durationMs: 45000
}
}对于聊天UI,请始终使用——这是用于展示的纯文本内容。字段包含内部推理步骤(仅用于调试,不适合展示)。
run.result?.answerreasoningSimple Chat Example (No Tools)
简单聊天示例(无工具)
For conversational chat without tools:
适用于不调用工具的对话式聊天场景:
Python
Python
python
from subconscious import Subconscious
client = Subconscious(api_key="your-api-key")python
from subconscious import Subconscious
client = Subconscious(api_key="your-api-key")Convert message history to instructions format
Convert message history to instructions format
messages = [
{"role": "user", "content": "Hello!"},
{"role": "assistant", "content": "Hi there! How can I help?"},
{"role": "user", "content": "Tell me about quantum computing"}
]
messages = [
{"role": "user", "content": "Hello!"},
{"role": "assistant", "content": "Hi there! How can I help?"},
{"role": "user", "content": "Tell me about quantum computing"}
]
Convert to instructions string
Convert to instructions string
instructions = "\n\n".join([
f"{'User' if m['role'] == 'user' else 'Assistant'}: {m['content']}"
for m in messages
]) + "\n\nRespond to the user's latest message."
run = client.run(
engine="tim-gpt",
input={"instructions": instructions, "tools": []},
options={"await_completion": True}
)
print(run.result.answer) # Clean text response
undefinedinstructions = "\n\n".join([
f"{'User' if m['role'] == 'user' else 'Assistant'}: {m['content']}"
for m in messages
]) + "\n\nRespond to the user's latest message."
run = client.run(
engine="tim-gpt",
input={"instructions": instructions, "tools": []},
options={"await_completion": True}
)
print(run.result.answer) # Clean text response
undefinedNode.js/TypeScript
Node.js/TypeScript
typescript
import { Subconscious } from "subconscious";
const client = new Subconscious({
apiKey: process.env.SUBCONSCIOUS_API_KEY!,
});
const messages = [
{ role: "user", content: "Hello!" },
{ role: "assistant", content: "Hi there! How can I help?" },
{ role: "user", content: "Tell me about quantum computing" }
];
// Convert to instructions string
const instructions = messages
.map(m => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`)
.join("\n\n") + "\n\nRespond to the user's latest message.";
const run = await client.run({
engine: "tim-gpt",
input: { instructions, tools: [] },
options: { awaitCompletion: true },
});
console.log(run.result?.answer); // Clean text responsetypescript
import { Subconscious } from "subconscious";
const client = new Subconscious({
apiKey: process.env.SUBCONSCIOUS_API_KEY!,
});
const messages = [
{ role: "user", content: "Hello!" },
{ role: "assistant", content: "Hi there! How can I help?" },
{ role: "user", content: "Tell me about quantum computing" }
];
// Convert to instructions string
const instructions = messages
.map(m => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`)
.join("\n\n") + "\n\nRespond to the user's latest message.";
const run = await client.run({
engine: "tim-gpt",
input: { instructions, tools: [] },
options: { awaitCompletion: true },
});
console.log(run.result?.answer); // Clean text responseInstructions Format vs Messages
指令格式与消息格式的区别
Important: Subconscious uses (single string), not array like OpenAI.
instructionsmessages- OpenAI format:
messages: [{role: "user", content: "..."}] - Subconscious format: (single string)
input: {instructions: "..."}
重要说明:Subconscious使用(单个字符串),而非OpenAI的数组格式。
instructionsmessages- OpenAI格式:
messages: [{role: "user", content: "..."}] - Subconscious格式:(单个字符串)
input: {instructions: "..."}
Converting Messages to Instructions
将消息转换为指令格式
typescript
function buildInstructions(
systemPrompt: string,
messages: Array<{role: string; content: string}>
): string {
const conversation = messages
.map(m => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`)
.join("\n\n");
return `${systemPrompt}typescript
function buildInstructions(
systemPrompt: string,
messages: Array<{role: string; content: string}>
): string {
const conversation = messages
.map(m => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`)
.join("\n\n");
return `${systemPrompt}Conversation History
Conversation History
${conversation}
${conversation}
Instructions
Instructions
Respond to the user's latest message.`;
}
// Usage
const instructions = buildInstructions(
"You are a helpful coding assistant. Be concise and use code examples.",
messages
);
undefinedRespond to the user's latest message.`;
}
// Usage
const instructions = buildInstructions(
"You are a helpful coding assistant. Be concise and use code examples.",
messages
);
undefinedSystem Prompts
系统提示词
Subconscious doesn't have a separate field. Prepend your system prompt to the instructions:
systemtypescript
const systemPrompt = "You are a helpful assistant. Always be concise.";
const userMessage = "Explain quantum computing";
const instructions = `${systemPrompt}
User: ${userMessage}
Respond to the user's message.`;Subconscious没有单独的字段,需将系统提示词前置到指令字符串中:
systemtypescript
const systemPrompt = "You are a helpful assistant. Always be concise.";
const userMessage = "Explain quantum computing";
const instructions = `${systemPrompt}
User: ${userMessage}
Respond to the user's message.`;Choosing an Engine
选择引擎
| Engine | API Name | Type | Best For |
|---|---|---|---|
| TIM | | Unified | Flagship unified agent engine for a wide range of tasks |
| TIM-Edge | | Unified | Speed, efficiency, search-heavy tasks |
| TIMINI | | Compound (Gemini-3 Flash backed) | Long-context and tool use, strong reasoning |
| TIM-GPT | | Compound (GPT-4.1 backed) | Most use cases, good balance of cost/performance |
| TIM-GPT-Heavy | | Compound (GPT-5.2 backed) | Maximum capability, complex reasoning |
Recommendation: Start with for most applications.
tim-gpt| 引擎 | API名称 | 类型 | 最佳适用场景 |
|---|---|---|---|
| TIM | | 统一型 | 适用于广泛任务的旗舰统一Agent引擎 |
| TIM-Edge | | 统一型 | 追求速度、效率和搜索密集型任务 |
| TIMINI | | 复合型(基于Gemini-3 Flash) | 长上下文和工具调用场景,推理能力强 |
| TIM-GPT | | 复合型(基于GPT-4.1) | 大多数使用场景,成本与性能平衡 |
| TIM-GPT-Heavy | | 复合型(基于GPT-5.2) | 最大能力,适用于复杂推理任务 |
推荐:大多数应用从开始使用。
tim-gptTools: The Key Differentiator
工具:核心差异化特性
Subconscious tools are remote HTTP endpoints. When the agent needs to use a tool, Subconscious makes an HTTP POST to the URL you specify. This is fundamentally different from OpenAI function calling where YOU handle tool execution in a loop.
Subconscious的工具是远程HTTP端点。当Agent需要使用工具时,Subconscious会向你指定的URL发起HTTP POST请求。这与OpenAI的函数调用本质不同,在OpenAI的模式中,你需要在循环中自行处理工具执行。
Tool Definition Format
工具定义格式
python
tools = [
{
"type": "function",
"name": "SearchTool",
"description": "a general search engine returns title, url, and description of 10 webpages",
"url": "https://your-server.com/search", # YOUR hosted endpoint
"method": "POST",
"timeout": 10, # seconds
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "A natural language query for the search engine."
}
},
"required": ["query"],
"additionalProperties": False
}
}
]Key fields unique to Subconscious:
- : The HTTP endpoint Subconscious will call when the agent uses this tool
url - : HTTP method (typically POST)
method - : How long to wait for tool response (seconds)
timeout
The agent decides when and how to call tools. You don't manage a tool-call loop. Subconscious handles multi-hop reasoning internally via TIMRUN.
python
tools = [
{
"type": "function",
"name": "SearchTool",
"description": "a general search engine returns title, url, and description of 10 webpages",
"url": "https://your-server.com/search", # YOUR hosted endpoint
"method": "POST",
"timeout": 10, # seconds
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "A natural language query for the search engine."
}
},
"required": ["query"],
"additionalProperties": False
}
}
]Subconscious独有的关键字段:
- :当Agent使用该工具时,Subconscious将调用的HTTP端点
url - :HTTP方法(通常为POST)
method - :等待工具响应的时长(秒)
timeout
Agent会自行决定何时以及如何调用工具,你无需管理工具调用循环。Subconscious通过TIMRUN在内部处理多跳推理。
Building a Tool Server
构建工具服务器
Your tool endpoint receives POST requests with parameters as JSON and returns JSON results.
FastAPI (Python):
python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class SearchRequest(BaseModel):
query: str
@app.post("/search")
async def search(req: SearchRequest):
# Your search logic here
return {
"results": [
{"title": "Result 1", "url": "https://example.com/1", "description": "..."}
]
}你的工具端点将接收包含JSON参数的POST请求,并返回JSON结果。
FastAPI(Python):
python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class SearchRequest(BaseModel):
query: str
@app.post("/search")
async def search(req: SearchRequest):
# Your search logic here
return {
"results": [
{"title": "Result 1", "url": "https://example.com/1", "description": "..."}
]
}Run with: uvicorn server:app --host 0.0.0.0 --port 8000
Run with: uvicorn server:app --host 0.0.0.0 --port 8000
**Express.js (Node.js):**
```typescript
import express from "express";
const app = express();
app.use(express.json());
app.post("/search", (req, res) => {
const { query } = req.body;
// Your search logic here
res.json({
results: [
{ title: "Result 1", url: "https://example.com/1", description: "..." }
]
});
});
app.listen(8000, () => console.log("Tool server running on :8000"));Important: Your endpoint must be publicly accessible. For local development, use ngrok or Cloudflare Tunnel.
**Express.js(Node.js):**
```typescript
import express from "express";
const app = express();
app.use(express.json());
app.post("/search", (req, res) => {
const { query } = req.body;
// Your search logic here
res.json({
results: [
{ title: "Result 1", url: "https://example.com/1", description: "..." }
]
});
});
app.listen(8000, () => console.log("Tool server running on :8000"));重要提示:你的端点必须可公开访问。本地开发时,可使用ngrok或Cloudflare Tunnel。
Structured Output
结构化输出
Structured output allows you to define the exact shape of the agent's response using JSON Schema. This ensures you receive data in a predictable, parseable format.
结构化输出允许你使用JSON Schema定义Agent响应的精确格式,确保你能获得可预测、可解析的数据格式。
When to Use Structured Output
何时使用结构化输出
Use structured output when you need:
- Responses that integrate with other systems
- Consistent data formats for downstream processing
- Type-safe responses in your application
当你需要以下功能时使用结构化输出:
- 与其他系统集成的响应
- 下游处理所需的一致数据格式
- 应用中的类型安全响应
Using answerFormat
使用answerFormat
The field accepts a JSON Schema that defines the structure of the agent's answer:
answerFormatPython:
python
from subconscious import Subconscious
client = Subconscious(api_key="your-api-key")
run = client.run(
engine="tim-gpt",
input={
"instructions": "Analyze the sentiment of this review: 'Great product, fast shipping!'",
"tools": [],
"answerFormat": {
"type": "object",
"title": "SentimentAnalysis",
"properties": {
"sentiment": {
"type": "string",
"enum": ["positive", "negative", "neutral"],
"description": "The overall sentiment"
},
"confidence": {
"type": "number",
"description": "Confidence score from 0 to 1"
},
"keywords": {
"type": "array",
"items": {"type": "string"},
"description": "Key phrases that influenced the sentiment"
}
},
"required": ["sentiment", "confidence", "keywords"]
}
},
options={"await_completion": True},
)answerFormatPython:
python
from subconscious import Subconscious
client = Subconscious(api_key="your-api-key")
run = client.run(
engine="tim-gpt",
input={
"instructions": "Analyze the sentiment of this review: 'Great product, fast shipping!'",
"tools": [],
"answerFormat": {
"type": "object",
"title": "SentimentAnalysis",
"properties": {
"sentiment": {
"type": "string",
"enum": ["positive", "negative", "neutral"],
"description": "The overall sentiment"
},
"confidence": {
"type": "number",
"description": "Confidence score from 0 to 1"
},
"keywords": {
"type": "array",
"items": {"type": "string"},
"description": "Key phrases that influenced the sentiment"
}
},
"required": ["sentiment", "confidence", "keywords"]
}
},
options={"await_completion": True},
)Response is already a dict matching your schema - no parsing needed
Response is already a dict matching your schema - no parsing needed
result = run.result.answer
print(result["sentiment"]) # "positive"
print(result["confidence"]) # 0.95
print(result["keywords"]) # ["Great product", "fast shipping"]
**Node.js/TypeScript:**
```typescript
import { Subconscious } from "subconscious";
const client = new Subconscious({
apiKey: process.env.SUBCONSCIOUS_API_KEY!,
});
const run = await client.run({
engine: "tim-gpt",
input: {
instructions: "Analyze the sentiment of this review: 'Great product, fast shipping!'",
tools: [],
answerFormat: {
type: "object",
title: "SentimentAnalysis",
properties: {
sentiment: {
type: "string",
enum: ["positive", "negative", "neutral"],
description: "The overall sentiment"
},
confidence: {
type: "number",
description: "Confidence score from 0 to 1"
},
keywords: {
type: "array",
items: { type: "string" },
description: "Key phrases that influenced the sentiment"
}
},
required: ["sentiment", "confidence", "keywords"]
}
},
options: { awaitCompletion: true },
});
// Response is already an object matching your schema - no parsing needed
const result = run.result?.answer;
console.log(result.sentiment); // "positive"
console.log(result.confidence); // 0.95
console.log(result.keywords); // ["Great product", "fast shipping"]Important: When using , returns a parsed object (dict in Python, object in JavaScript), not a JSON string. You can access fields directly without parsing.
answerFormatrun.result.answerresult = run.result.answer
print(result["sentiment"]) # "positive"
print(result["confidence"]) # 0.95
print(result["keywords"]) # ["Great product", "fast shipping"]
**Node.js/TypeScript:**
```typescript
import { Subconscious } from "subconscious";
const client = new Subconscious({
apiKey: process.env.SUBCONSCIOUS_API_KEY!,
});
const run = await client.run({
engine: "tim-gpt",
input: {
instructions: "Analyze the sentiment of this review: 'Great product, fast shipping!'",
tools: [],
answerFormat: {
type: "object",
title: "SentimentAnalysis",
properties: {
sentiment: {
type: "string",
enum: ["positive", "negative", "neutral"],
description: "The overall sentiment"
},
confidence: {
type: "number",
description: "Confidence score from 0 to 1"
},
keywords: {
type: "array",
items: { type: "string" },
description: "Key phrases that influenced the sentiment"
}
},
required: ["sentiment", "confidence", "keywords"]
}
},
options: { awaitCompletion: true },
});
// Response is already an object matching your schema - no parsing needed
const result = run.result?.answer;
console.log(result.sentiment); // "positive"
console.log(result.confidence); // 0.95
console.log(result.keywords); // ["Great product", "fast shipping"]重要提示:使用时,返回的是已解析的对象(Python中的dict,JavaScript中的object),而非JSON字符串。你可以直接访问字段,无需解析。
answerFormatrun.result.answerUsing Pydantic Models (Python)
使用Pydantic模型(Python)
The Python SDK automatically converts Pydantic models to JSON Schema:
python
from subconscious import Subconscious
from pydantic import BaseModel
class SentimentAnalysis(BaseModel):
sentiment: str
confidence: float
keywords: list[str]
client = Subconscious(api_key="your-api-key")
run = client.run(
engine="tim-gpt",
input={
"instructions": "Analyze the sentiment of: 'Great product!'",
"answerFormat": SentimentAnalysis, # Pass the class directly
},
options={"await_completion": True},
)
print(run.result.answer["sentiment"])Python SDK会自动将Pydantic模型转换为JSON Schema:
python
from subconscious import Subconscious
from pydantic import BaseModel
class SentimentAnalysis(BaseModel):
sentiment: str
confidence: float
keywords: list[str]
client = Subconscious(api_key="your-api-key")
run = client.run(
engine="tim-gpt",
input={
"instructions": "Analyze the sentiment of: 'Great product!'",
"answerFormat": SentimentAnalysis, # Pass the class directly
},
options={"await_completion": True},
)
print(run.result.answer["sentiment"])Using Zod (Node.js/TypeScript)
使用Zod(Node.js/TypeScript)
For TypeScript, we recommend using Zod to define your schema:
typescript
import { z } from 'zod';
import { Subconscious, zodToJsonSchema } from 'subconscious';
const AnalysisSchema = z.object({
summary: z.string().describe('A brief summary of the findings'),
keyPoints: z.array(z.string()).describe('Main takeaways'),
sentiment: z.enum(['positive', 'neutral', 'negative']),
confidence: z.number().describe('Confidence score from 0 to 1'),
});
const client = new Subconscious({
apiKey: process.env.SUBCONSCIOUS_API_KEY!,
});
const run = await client.run({
engine: 'tim-gpt',
input: {
instructions: 'Analyze the latest news about electric vehicles',
tools: [{ type: 'platform', id: 'fast_search' }],
answerFormat: zodToJsonSchema(AnalysisSchema, 'Analysis'),
},
options: { awaitCompletion: true },
});
// Result is typed according to your schema
const result = run.result?.answer as z.infer<typeof AnalysisSchema>;
console.log(result.summary);
console.log(result.keyPoints);对于TypeScript,我们推荐使用Zod定义你的Schema:
typescript
import { z } from 'zod';
import { Subconscious, zodToJsonSchema } from 'subconscious';
const AnalysisSchema = z.object({
summary: z.string().describe('A brief summary of the findings'),
keyPoints: z.array(z.string()).describe('Main takeaways'),
sentiment: z.enum(['positive', 'neutral', 'negative']),
confidence: z.number().describe('Confidence score from 0 to 1'),
});
const client = new Subconscious({
apiKey: process.env.SUBCONSCIOUS_API_KEY!,
});
const run = await client.run({
engine: 'tim-gpt',
input: {
instructions: 'Analyze the latest news about electric vehicles',
tools: [{ type: 'platform', id: 'fast_search' }],
answerFormat: zodToJsonSchema(AnalysisSchema, 'Analysis'),
},
options: { awaitCompletion: true },
});
// Result is typed according to your schema
const result = run.result?.answer as z.infer<typeof AnalysisSchema>;
console.log(result.summary);
console.log(result.keyPoints);Structured Reasoning (Optional)
结构化推理(可选)
You can also structure the reasoning output using :
reasoningFormattypescript
const ReasoningSchema = z.object({
steps: z.array(z.object({
thought: z.string(),
action: z.string(),
})),
conclusion: z.string(),
});
const run = await client.run({
engine: 'tim-gpt',
input: {
instructions: 'Research and analyze a topic',
tools: [],
reasoningFormat: zodToJsonSchema(ReasoningSchema, 'Reasoning'),
},
options: { awaitCompletion: true },
});
const reasoning = run.result?.reasoning; // Structured reasoning你也可以使用结构化推理输出:
reasoningFormattypescript
const ReasoningSchema = z.object({
steps: z.array(z.object({
thought: z.string(),
action: z.string(),
})),
conclusion: z.string(),
});
const run = await client.run({
engine: 'tim-gpt',
input: {
instructions: 'Research and analyze a topic',
tools: [],
reasoningFormat: zodToJsonSchema(ReasoningSchema, 'Reasoning'),
},
options: { awaitCompletion: true },
});
const reasoning = run.result?.reasoning; // Structured reasoningSchema Requirements
Schema要求
- Must be valid JSON Schema
- Use for structured responses
type: "object" - Include field for better results
title - Define for each field
properties - Use array for mandatory fields
required - Set to prevent extra fields
additionalProperties: false
See for more details on structured output.
references/api-reference.md- 必须是有效的JSON Schema
- 结构化响应使用
type: "object" - 包含字段以获得更好的结果
title - 为每个字段定义
properties - 使用数组定义必填字段
required - 设置以防止额外字段
additionalProperties: false
有关结构化输出的更多详细信息,请参阅。
references/api-reference.mdrun() vs stream() - Critical Difference
run() vs stream() - 关键区别
Use run()
for Chat UIs (Recommended)
run()聊天UI使用run()
(推荐)
run()Method:
Behavior: Waits for completion, returns clean answer
What you get: = clean text for display
Best for: Chat UIs, simple responses, production apps
run({ options: { awaitCompletion: true } })Behavior: Waits for completion, returns clean answer
What you get:
run.result?.answerBest for: Chat UIs, simple responses, production apps
typescript
const run = await client.run({
engine: "tim-gpt",
input: { instructions: "Your prompt", tools: [] },
options: { awaitCompletion: true }
});
const answer = run.result?.answer; // Clean text - use this for display
const reasoning = run.result?.reasoning; // Optional: step-by-step reasoning方法:
行为:等待完成,返回纯文本响应
返回结果: = 用于展示的纯文本
最佳适用场景:聊天UI、简单响应、生产应用
run({ options: { awaitCompletion: true } })行为:等待完成,返回纯文本响应
返回结果:
run.result?.answer最佳适用场景:聊天UI、简单响应、生产应用
typescript
const run = await client.run({
engine: "tim-gpt",
input: { instructions: "Your prompt", tools: [] },
options: { awaitCompletion: true }
});
const answer = run.result?.answer; // Clean text - use this for display
const reasoning = run.result?.reasoning; // Optional: step-by-step reasoningUse stream()
for Real-time Reasoning Display
stream()实时推理展示使用stream()
stream()Method:
Behavior: Streams JSON incrementally as it's built
What you get: Raw JSON chunks building toward:
stream()Behavior: Streams JSON incrementally as it's built
What you get: Raw JSON chunks building toward:
{"reasoning": [...], "answer": "..."}WARNING: The stream content is raw JSON characters, not clean text. You must parse it.
方法:
行为:增量流式传输JSON数据
返回结果:原始JSON片段,最终组合为:
stream()行为:增量流式传输JSON数据
返回结果:原始JSON片段,最终组合为:
{"reasoning": [...], "answer": "..."}警告:流式内容是原始JSON字符,而非纯文本,你必须自行解析。
What the stream looks like:
流式返回示例:
delta: {"rea
delta: soning": [{"th
delta: ought": "Analyzing
...
delta: "}], "answer": "Here's the answer"}
done: {runId: "run_xxx"}delta: {"rea
delta: soning": [{"th
delta: ought": "Analyzing
...
delta: "}], "answer": "Here's the answer"}
done: {runId: "run_xxx"}When to use stream():
何时使用stream():
| Use Case | Method | Why |
|---|---|---|
| Show thinking in real-time | | Users see reasoning as it happens (like ChatGPT) |
| Simple chat, fast response | | Easier, returns clean |
| Background processing | | Poll for status |
| 使用场景 | 方法 | 原因 |
|---|---|---|
| 实时展示思考过程 | | 用户可实时看到推理步骤(类似ChatGPT) |
| 简单聊天、快速响应 | | 更简单,直接返回纯文本响应 |
| 后台处理 | 不设置 | 轮询状态 |
How to use stream() for reasoning UI:
如何使用stream()构建推理UI:
See for complete implementation including:
references/streaming-and-reasoning.md- How to extract thoughts from the JSON stream
- Next.js API route example
- React component for displaying reasoning
- CSS styling
Quick example:
typescript
const stream = client.stream({
engine: "tim-gpt",
input: { instructions: "Your prompt", tools: [] }
});
let fullContent = "";
for await (const event of stream) {
if (event.type === "delta") {
fullContent += event.content;
// Extract thoughts using regex (see streaming-and-reasoning.md)
const thoughts = extractThoughts(fullContent);
// Send to UI
} else if (event.type === "done") {
const final = JSON.parse(fullContent);
const answer = final.answer; // Extract final answer
}
}For most chat UIs, use instead - it's simpler and returns clean text directly.
run()完整实现请参阅,包括:
references/streaming-and-reasoning.md- 如何从JSON流中提取思考内容
- Next.js API路由示例
- 用于展示推理的React组件
- CSS样式
快速示例:
typescript
const stream = client.stream({
engine: "tim-gpt",
input: { instructions: "Your prompt", tools: [] }
});
let fullContent = "";
for await (const event of stream) {
if (event.type === "delta") {
fullContent += event.content;
// Extract thoughts using regex (see streaming-and-reasoning.md)
const thoughts = extractThoughts(fullContent);
// Send to UI
} else if (event.type === "done") {
const final = JSON.parse(fullContent);
const answer = final.answer; // Extract final answer
}
}对于大多数聊天UI,建议使用——更简单,直接返回纯文本内容。
run()API Modes
API模式
Sync Mode (Recommended for Chat)
同步模式(聊天场景推荐)
python
run = client.run(
engine="tim-gpt",
input={"instructions": "Your task", "tools": tools},
options={"await_completion": True}
)
answer = run.result.answer # Clean textpython
run = client.run(
engine="tim-gpt",
input={"instructions": "Your task", "tools": tools},
options={"await_completion": True}
)
answer = run.result.answer # Clean textAsync Mode
异步模式
For long-running jobs, don't set :
await_completionpython
run = client.run(
engine="tim-gpt",
input={"instructions": "Long task", "tools": tools}
# No await_completion - returns immediately
)
run_id = run.run_id对于长时间运行的任务,请勿设置:
await_completionpython
run = client.run(
engine="tim-gpt",
input={"instructions": "Long task", "tools": tools}
# No await_completion - returns immediately
)
run_id = run.run_idPoll for status
Poll for status
status = client.get(run_id)
while status.status not in ["succeeded", "failed"]:
time.sleep(2)
status = client.get(run_id)
answer = status.result.answer
undefinedstatus = client.get(run_id)
while status.status not in ["succeeded", "failed"]:
time.sleep(2)
status = client.get(run_id)
answer = status.result.answer
undefinedStreaming (Advanced)
流式传输(高级)
See for streaming examples. Note: Streaming returns raw JSON, not clean text.
references/examples.md流式传输示例请参阅。注意:流式传输返回的是原始JSON,而非纯文本。
references/examples.mdSDK Methods Reference
SDK方法参考
| Method | Description | When to Use |
|---|---|---|
| Create a run (sync or async) | Most common - create agent runs |
| Stream run events in real-time | Chat UIs, live demos |
| Get current status of a run | Check async run status |
| Poll until run completes | Background jobs, dashboards |
| Cancel a running/queued run | User cancellation, timeouts |
| 方法 | 描述 | 何时使用 |
|---|---|---|
| 创建一个运行任务(同步或异步) | 最常用 - 创建Agent运行任务 |
| 实时流式传输运行事件 | 聊天UI、实时演示 |
| 获取运行任务的当前状态 | 检查异步任务状态 |
| 轮询直到任务完成 | 后台任务、仪表板 |
| 取消运行中/排队的任务 | 用户取消、超时 |
client.get()
client.get()
Get the current status of a run:
python
status = client.get(run.run_id)
print(status.status) # 'queued' | 'running' | 'succeeded' | 'failed'
if status.status == "succeeded":
print(status.result.answer)typescript
const status = await client.get(run.runId);
console.log(status.status);
if (status.status === "succeeded") {
console.log(status.result?.answer);
}获取运行任务的当前状态:
python
status = client.get(run.run_id)
print(status.status) # 'queued' | 'running' | 'succeeded' | 'failed'
if status.status == "succeeded":
print(status.result.answer)typescript
const status = await client.get(run.runId);
console.log(status.status);
if (status.status === "succeeded") {
console.log(status.result?.answer);
}client.wait()
client.wait()
Automatically poll until a run completes:
python
result = client.wait(
run.run_id,
options={
"interval_ms": 2000, # Poll every 2 seconds (default)
"max_attempts": 60, # Max attempts before giving up (default: 60)
},
)typescript
const result = await client.wait(run.runId, {
intervalMs: 2000, // Poll every 2 seconds
maxAttempts: 60, // Max attempts before giving up
});自动轮询直到任务完成:
python
result = client.wait(
run.run_id,
options={
"interval_ms": 2000, # Poll every 2 seconds (default)
"max_attempts": 60, # Max attempts before giving up (default: 60)
},
)typescript
const result = await client.wait(run.runId, {
intervalMs: 2000, # Poll every 2 seconds
maxAttempts: 60, # Max attempts before giving up
});client.cancel()
client.cancel()
Cancel a run that's still in progress:
python
client.cancel(run.run_id)typescript
await client.cancel(run.runId);取消仍在进行中的任务:
python
client.cancel(run.run_id)typescript
await client.cancel(run.runId);Common Patterns
常见模式
Research Agent
研究型Agent
python
tools = [
{
"type": "function",
"name": "web_search",
"description": "Search the web for current information",
"url": "https://your-server.com/search",
"method": "POST",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"}
},
"required": ["query"]
}
}
]
run = client.run(
engine="tim-gpt",
input={
"instructions": "Research the latest AI breakthroughs",
"tools": tools
},
options={"await_completion": True}
)
print(run.result.answer)python
tools = [
{
"type": "function",
"name": "web_search",
"description": "Search the web for current information",
"url": "https://your-server.com/search",
"method": "POST",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"}
},
"required": ["query"]
}
}
]
run = client.run(
engine="tim-gpt",
input={
"instructions": "Research the latest AI breakthroughs",
"tools": tools
},
options={"await_completion": True}
)
print(run.result.answer)Multi-Tool Agent
多工具Agent
Define multiple tools. The agent will chain them as needed:
python
tools = [
{
"type": "function",
"name": "search",
"description": "Search the web",
"url": "https://your-server.com/search",
"method": "POST",
"parameters": {...}
},
{
"type": "function",
"name": "save_to_db",
"description": "Save results to database",
"url": "https://your-server.com/save",
"method": "POST",
"parameters": {...}
}
]定义多个工具,Agent会根据需要链式调用:
python
tools = [
{
"type": "function",
"name": "search",
"description": "Search the web",
"url": "https://your-server.com/search",
"method": "POST",
"parameters": {...}
},
{
"type": "function",
"name": "save_to_db",
"description": "Save results to database",
"url": "https://your-server.com/save",
"method": "POST",
"parameters": {...}
}
]TypeScript Types
TypeScript类型
SDK Exports
SDK导出
typescript
import {
Subconscious,
type RunResponse,
type StreamEvent,
type ReasoningStep,
type Tool,
type SubconsciousError
} from "subconscious";typescript
import {
Subconscious,
type RunResponse,
type StreamEvent,
type ReasoningStep,
type Tool,
type SubconsciousError
} from "subconscious";Response Types
响应类型
typescript
interface RunResponse {
runId: string;
status: "queued" | "running" | "succeeded" | "failed" | "canceled" | "timed_out";
result?: {
answer: string; // Clean text response
reasoning?: ReasoningStep[]; // Optional: step-by-step reasoning
};
usage?: {
inputTokens: number;
outputTokens: number;
durationMs: number;
toolCalls?: { [toolName: string]: number };
};
error?: {
code: string;
message: string;
};
}
interface ReasoningStep {
title?: string;
thought?: string;
conclusion?: string;
tooluse?: {
tool_name: string;
parameters: Record<string, unknown>;
tool_result: unknown;
};
subtasks?: ReasoningStep[];
}
interface StreamEvent {
type: "delta" | "done" | "error";
content?: string; // Raw JSON chunk for delta events
runId?: string; // Present on done
message?: string; // Present on error
}typescript
interface RunResponse {
runId: string;
status: "queued" | "running" | "succeeded" | "failed" | "canceled" | "timed_out";
result?: {
answer: string; // Clean text response
reasoning?: ReasoningStep[]; // Optional: step-by-step reasoning
};
usage?: {
inputTokens: number;
outputTokens: number;
durationMs: number;
toolCalls?: { [toolName: string]: number };
};
error?: {
code: string;
message: string;
};
}
interface ReasoningStep {
title?: string;
thought?: string;
conclusion?: string;
tooluse?: {
tool_name: string;
parameters: Record<string, unknown>;
tool_result: unknown;
};
subtasks?: ReasoningStep[];
}
interface StreamEvent {
type: "delta" | "done" | "error";
content?: string; // Raw JSON chunk for delta events
runId?: string; // Present on done
message?: string; // Present on error
}Error Handling
错误处理
SDK Errors
SDK错误
typescript
import { SubconsciousError } from "subconscious";
try {
const run = await client.run({
engine: "tim-gpt",
input: { instructions: "...", tools: [] },
options: { awaitCompletion: true }
});
} catch (error) {
if (error instanceof SubconsciousError) {
switch (error.code) {
case "invalid_api_key":
// Redirect to settings
console.error("Invalid API key");
break;
case "rate_limited":
// Show retry message
console.error("Rate limited, retry later");
break;
case "insufficient_credits":
// Prompt to add credits
console.error("Insufficient credits");
break;
case "invalid_request":
// Log for debugging
console.error("Invalid request:", error.message);
break;
case "timeout":
// Offer to retry with longer timeout
console.error("Request timed out");
break;
default:
console.error("Error:", error.message);
}
} else {
// Network or other errors
console.error("Unexpected error:", error);
}
}typescript
import { SubconsciousError } from "subconscious";
try {
const run = await client.run({
engine: "tim-gpt",
input: { instructions: "...", tools: [] },
options: { awaitCompletion: true }
});
} catch (error) {
if (error instanceof SubconsciousError) {
switch (error.code) {
case "invalid_api_key":
// Redirect to settings
console.error("Invalid API key");
break;
case "rate_limited":
// Show retry message
console.error("Rate limited, retry later");
break;
case "insufficient_credits":
// Prompt to add credits
console.error("Insufficient credits");
break;
case "invalid_request":
// Log for debugging
console.error("Invalid request:", error.message);
break;
case "timeout":
// Offer to retry with longer timeout
console.error("Request timed out");
break;
default:
console.error("Error:", error.message);
}
} else {
// Network or other errors
console.error("Unexpected error:", error);
}
}HTTP Status Codes
HTTP状态码
| Status | Code | Meaning | Action |
|---|---|---|---|
| 400 | | Bad request parameters | Fix request |
| 401 | | Invalid or missing API key | Check API key |
| 402 | | Account needs credits | Add credits |
| 429 | | Too many requests | Retry after delay |
| 500 | | Server error | Retry with backoff |
| 503 | | Service down | Retry later |
| 状态码 | 错误码 | 含义 | 处理方式 |
|---|---|---|---|
| 400 | | 请求参数错误 | 修正请求 |
| 401 | | API密钥无效或缺失 | 检查API密钥 |
| 402 | | 账户余额不足 | 充值 |
| 429 | | 请求过于频繁 | 延迟后重试 |
| 500 | | 服务器错误 | 指数退避重试 |
| 503 | | 服务不可用 | 稍后重试 |
Run-Level Errors
任务级错误
Runs can fail after being accepted. Always check status:
typescript
const run = await client.run({...});
if (run.status === "succeeded") {
console.log(run.result?.answer);
} else if (run.status === "failed") {
console.error("Run failed:", run.error?.message);
} else if (run.status === "timed_out") {
console.error("Run timed out");
}任务在被接受后仍可能失败,务必检查状态:
typescript
const run = await client.run({...});
if (run.status === "succeeded") {
console.log(run.result?.answer);
} else if (run.status === "failed") {
console.error("Run failed:", run.error?.message);
} else if (run.status === "timed_out") {
console.error("Run timed out");
}Request Cancellation
请求取消
Using AbortController
使用AbortController
typescript
const controller = new AbortController();
// Start the request
const runPromise = client.run({
engine: "tim-gpt",
input: { instructions: "...", tools: [] },
options: { awaitCompletion: true }
});
// Cancel after 10 seconds
setTimeout(() => controller.abort(), 10000);
// Or cancel on user action
cancelButton.onclick = () => controller.abort();
try {
const run = await runPromise;
} catch (error) {
if (error.name === "AbortError") {
console.log("Request cancelled by user");
}
}typescript
const controller = new AbortController();
// Start the request
const runPromise = client.run({
engine: "tim-gpt",
input: { instructions: "...", tools: [] },
options: { awaitCompletion: true }
});
// Cancel after 10 seconds
setTimeout(() => controller.abort(), 10000);
// Or cancel on user action
cancelButton.onclick = () => controller.abort();
try {
const run = await runPromise;
} catch (error) {
if (error.name === "AbortError") {
console.log("Request cancelled by user");
}
}Cancelling Async Runs
取消异步任务
typescript
// Start async run
const run = await client.run({
engine: "tim-gpt",
input: { instructions: "...", tools: [] }
// No awaitCompletion
});
// Cancel it
await client.cancel(run.runId);typescript
// Start async run
const run = await client.run({
engine: "tim-gpt",
input: { instructions: "...", tools: [] }
// No awaitCompletion
});
// Cancel it
await client.cancel(run.runId);Common Gotchas
常见误区
CRITICAL: Streaming Returns Raw JSON, Not Text
重点注意:流式返回的是原始JSON,而非文本
The #1 mistake: Displaying from directly in the UI shows ugly raw JSON like .
event.contentstream(){"reasoning":[{"thought":"I need to...The fix: Extract thoughts and answer from the JSON:
typescript
// BAD - shows raw JSON in UI
for await (const event of stream) {
if (event.type === "delta") {
displayToUser(event.content); // Shows: {"rea... (ugly!)
}
}
// GOOD - extract thoughts and show clean text
let fullContent = "";
let sentThoughts: string[] = [];
for await (const event of stream) {
if (event.type === "delta") {
fullContent += event.content;
// Extract thoughts using regex
const thoughtPattern = /"thought"\s*:\s*"((?:[^"\\]|\\.)*)"/g;
let match;
while ((match = thoughtPattern.exec(fullContent)) !== null) {
const thought = match[1].replace(/\\n/g, " ").replace(/\\"/g, '"');
if (!sentThoughts.includes(thought)) {
displayThinking(thought); // Shows: "I need to search for movies..."
sentThoughts.push(thought);
}
}
} else if (event.type === "done") {
const parsed = JSON.parse(fullContent);
displayAnswer(parsed.answer); // Shows clean final answer
}
}See for complete implementation.
references/streaming-and-reasoning.md- Use for display - Not
run.result?.answer(that's OpenAI format)choices[0].message.content - returns raw JSON - Use
stream()for clean text answers in chat UIs. Seerun()for parsing.references/streaming-and-reasoning.md - No endpoint - Use the native SDK, not OpenAI SDK
/chat/completions - Instructions format, not messages - Convert message history to single string
- Tools must be publicly accessible - Use ngrok for local development
- Response has - The clean text is in
result.answer, notresult.answerresult.content - Reasoning field is optional - Contains internal steps, useful for debugging
- Engine names: Use ,
tim,tim-edge,timini,tim-gpttim-gpt-heavy - Streaming shows raw JSON - You must parse yourself. For simple chat, use
{"reasoning": [...], "answer": "..."}instead.run() - is required - Even if you have no tools, pass an empty array.
tools: [] - No system message field - Prepend system prompt to your instructions string.
- Always check - Don't access
run.statuswithout checking status first.run.result
最常见错误:在UI中直接展示返回的,会显示丑陋的原始JSON,例如。
stream()event.content{"reasoning":[{"thought":"I need to...解决方法:从JSON中提取思考内容和响应文本:
typescript
// BAD - shows raw JSON in UI
for await (const event of stream) {
if (event.type === "delta") {
displayToUser(event.content); // Shows: {"rea... (ugly!)
}
}
// GOOD - extract thoughts and show clean text
let fullContent = "";
let sentThoughts: string[] = [];
for await (const event of stream) {
if (event.type === "delta") {
fullContent += event.content;
// Extract thoughts using regex
const thoughtPattern = /"thought"\s*:\s*"((?:[^"\\]|\\.)*)"/g;
let match;
while ((match = thoughtPattern.exec(fullContent)) !== null) {
const thought = match[1].replace(/\\n/g, " ").replace(/\\"/g, '"');
if (!sentThoughts.includes(thought)) {
displayThinking(thought); // Shows: "I need to search for movies..."
sentThoughts.push(thought);
}
}
} else if (event.type === "done") {
const parsed = JSON.parse(fullContent);
displayAnswer(parsed.answer); // Shows clean final answer
}
}完整实现请参阅。
references/streaming-and-reasoning.md- 使用进行展示 - 不要使用
run.result?.answer(这是OpenAI格式)choices[0].message.content - 返回原始JSON - 聊天UI中请使用
stream()获取纯文本响应。解析方法请参阅run()references/streaming-and-reasoning.md - 没有端点 - 使用原生SDK,而非OpenAI SDK
/chat/completions - 使用指令格式,而非消息格式 - 将消息历史转换为单个字符串
- 工具必须可公开访问 - 本地开发时使用ngrok
- 响应包含- 纯文本内容在
result.answer中,而非result.answerresult.content - Reasoning字段是可选的 - 包含内部步骤,仅用于调试
- 引擎名称:使用,
tim,tim-edge,timini,tim-gpttim-gpt-heavy - 流式返回的是原始JSON - 你必须自行解析。简单聊天场景请使用
{"reasoning": [...], "answer": "..."}run() - 是必填项 - 即使没有工具,也需传入空数组
tools: [] - 没有系统消息字段 - 将系统提示词前置到指令字符串中
- 务必检查- 访问
run.status前必须先检查状态run.result
Next.js/Vercel Example
Next.js/Vercel示例
See for complete Next.js API route example with Server-Sent Events.
references/examples.md完整的Next.js API路由示例(包含Server-Sent Events)请参阅。
references/examples.mdProduction Checklist
生产环境检查清单
Security
安全
- API key in environment variables, never client-side
- Rate limiting on your API routes
- Input validation (max message length, sanitization)
- CORS configuration for production domains
- API密钥存储在环境变量中,绝不要暴露在客户端
- API路由设置速率限制
- 输入验证(最大消息长度、内容清理)
- 生产环境域名的CORS配置
Reliability
可靠性
- Retry logic with exponential backoff for 5xx errors
- Timeout configuration (default may be too short for complex tasks)
- Graceful error messages for users
- Health check endpoint
- 针对5xx错误的指数退避重试逻辑
- 超时配置(默认值可能不适用于复杂任务)
- 为用户提供友好的错误提示
- 健康检查端点
Monitoring
监控
- Log for cost tracking
run.usage - Track for latency monitoring
run.usage.durationMs - Alert on error rate spikes
- Monitor for tool usage patterns
run.usage.toolCalls
- 记录以跟踪成本
run.usage - 跟踪以监控延迟
run.usage.durationMs - 错误率峰值告警
- 监控以分析工具使用模式
run.usage.toolCalls
UX
用户体验
- Loading states while waiting for response
- Ability to cancel long-running requests
- Show reasoning/thinking indicators (if using stream())
- Error recovery (retry buttons)
- Clear error messages
- 等待响应时的加载状态
- 取消长时间运行请求的功能
- 推理/思考状态指示器(如果使用stream())
- 错误恢复(重试按钮)
- 清晰的错误提示
Cost Control
成本控制
- Use or
timfor simple tasks,tim-edgeonly when neededtim-gpt-heavy - Implement usage quotas per user if needed
- Monitor token usage in production
- 简单任务使用或
tim,仅在必要时使用tim-edgetim-gpt-heavy - 如需,为每个用户设置使用配额
- 生产环境中监控token使用量
Reference Files
参考文档
For detailed information, see:
- - Complete API documentation with correct response formats
references/api-reference.md - - CRITICAL: How to stream and display reasoning steps (solves the raw JSON problem)
references/streaming-and-reasoning.md - - Complete TypeScript type definitions
references/typescript-types.md - - Error handling patterns and best practices
references/error-handling.md - - Deep dive on tool system
references/tools-guide.md - - Complete working examples including Next.js and reasoning display
references/examples.md
更多详细信息,请参阅:
- - 完整的API文档,包含正确的响应格式
references/api-reference.md - - 重点:如何流式传输和展示推理步骤(解决原始JSON问题)
references/streaming-and-reasoning.md - - 完整的TypeScript类型定义
references/typescript-types.md - - 错误处理模式和最佳实践
references/error-handling.md - - 工具系统深度解析
references/tools-guide.md - - 完整的工作示例,包括Next.js和推理展示
references/examples.md
Resources
资源
- Docs: https://docs.subconscious.dev
- Platform: https://subconscious.dev/platform
- Playground: https://subconscious.dev/playground
- Python SDK: https://github.com/subconscious-systems/subconscious-python
- Node SDK: https://github.com/subconscious-systems/subconscious-node
- Examples: https://github.com/subconscious-systems/subconscious/tree/main/examples
When in doubt, check the official docs at docs.subconscious.dev for the latest information.
- 官方文档:https://docs.subconscious.dev
- 平台:https://subconscious.dev/platform
- 在线演示:https://subconscious.dev/playground
- Python SDK:https://github.com/subconscious-systems/subconscious-python
- Node SDK:https://github.com/subconscious-systems/subconscious-node
- 示例:https://github.com/subconscious-systems/subconscious/tree/main/examples
如有疑问,请查阅官方文档docs.subconscious.dev获取最新信息。