Agent Guide
Overview
Section titled “Overview”This guide walks you through creating an agent that answers questions from a document bucket and a custom tool. By the end you will have a working TypeScript agent that searches documents, calls a tool, and emits events you can observe.
Prerequisites
Section titled “Prerequisites”- Node.js 18 or later
- A Schift workspace API key (
sch_...) - A configured API origin for your workspace
- The Schift CLI installed (only needed to create and populate the bucket)
Note: If you have not yet created a bucket and verified search, follow the Quickstart first. Proving the retrieval path before adding an agent makes debugging much easier.
Step 1: Install the SDK
Section titled “Step 1: Install the SDK”npm install @schift-io/sdkStep 2: Prepare a knowledge bucket
Section titled “Step 2: Prepare a knowledge bucket”Create a bucket and upload at least one document:
export SCHIFT_API_KEY=sch_...export SCHIFT_API_URL=https://api.example.com/v1
schift db create support-docsschift upload ./handbook.pdf --bucket support-docsschift search "How do I reset my password?" --bucket support-docs --top-k 5Confirm that search returns relevant chunks. Once it does, the same bucket can be attached to an agent.
Step 3: Create the agent
Section titled “Step 3: Create the agent”Create a file named agent.ts:
import { Schift, Agent, RAG } from "@schift-io/sdk";
const schift = new Schift({ apiKey: process.env.SCHIFT_API_KEY,});
const rag = new RAG({ bucket: "support-docs" }, schift.transport);
const agent = new Agent({ name: "Support Bot", instructions: "You are a support assistant. Answer questions using the knowledge base. " + "If the answer is not in the documents, say so clearly.", rag, model: "gpt-4o-mini", transport: schift.transport, maxSteps: 10,});The RAG instance is automatically registered as a tool named rag_search, so the agent can search the bucket whenever the question requires it.
Step 4: Run the agent
Section titled “Step 4: Run the agent”const result = await agent.run("How do I reset my password?");
console.log(result.output);console.log(`Completed in ${result.totalDurationMs}ms`);console.log(`Steps: ${result.steps.length}`);Each step in result.steps has a type such as think, tool_call, tool_result, or final_answer. Inspecting the steps is the fastest way to understand why an agent produced a particular answer.
Step 5: Add a custom tool
Section titled “Step 5: Add a custom tool”Agents become more useful when they can call your own APIs. Add a weather tool:
import type { AgentTool } from "@schift-io/sdk";
const getWeather: AgentTool = { name: "get_weather", description: "Get the current weather for a city", parameters: { type: "object", properties: { city: { type: "string", description: "City name, for example Seoul", }, }, required: ["city"], }, handler: async (args) => { const city = String(args.city); const temperature = await fetchWeatherAPI(city); // your implementation return { success: true, data: { city, temperature } }; },};
const agent = new Agent({ name: "Support Bot", instructions: "Answer support questions and report weather when asked.", rag, tools: [getWeather], transport: schift.transport,});Tool names must be unique within an agent, use snake_case, and match /^[a-zA-Z_][a-zA-Z0-9_]*$/.
Step 6: Observe events
Section titled “Step 6: Observe events”Subscribe to events to show progress or log execution:
agent.on("tool_call", (event) => { console.log(`Calling tool: ${event.toolName}`);});
agent.on("tool_result", (event) => { console.log(`Tool result:`, event.result);});
agent.on("agent_end", (event) => { console.log(`Run finished in ${event.totalDurationMs}ms`);});
const result = await agent.run("What is the weather in Seoul?");The returned cleanup function removes the listener when you no longer need it:
const unsub = agent.on("tool_call", handler);unsub();Step 7: Handle errors
Section titled “Step 7: Handle errors”Wrap runs in try/catch to handle agent-level failures:
import { AgentError, MaxStepsError } from "@schift-io/sdk";
try { const result = await agent.run("A very complex question"); console.log(result.output);} catch (err) { if (err instanceof MaxStepsError) { console.log("The agent used too many steps. Try a simpler question or increase maxSteps."); } else if (err instanceof AgentError) { console.log(`Agent error: ${err.message}`); }}If the agent hits maxSteps, agent.run() returns normally and the final step has type error. Check result.steps to see where the loop ended.
Next steps
Section titled “Next steps”- Add web search for questions that need current information.
- Read the Agent concept for a deeper explanation of the ReAct loop and configuration options.
- Explore Tools and Skills to extend what your agent can do.
- Review Error Handling for production-ready patterns.