Skip to content

Quickstart

Get up and running with Tavora in five minutes. This guide walks you through initializing the SDK, creating an index, uploading a document, searching it, and running an agent. Code samples are shown in Go and TypeScript; the REST equivalent is one tab over.

  • A Tavora app with an API key (mint one in the admin web UI — covered in the platform’s internal docs).
  • Optional: the tavora CLI installed, with tavora init run to save your credentials.
  • Go 1.25+ or Node ≥ 20.
Terminal window
go get github.com/tavora-ai/tavora-sdk-go
package main
import (
"context"
"fmt"
"log"
tavora "github.com/tavora-ai/tavora-sdk-go"
)
func main() {
client := tavora.NewClient(
"https://api.tavora.ai", // or http://localhost:8080 in dev
"tvr_your-api-key",
)
ctx := context.Background()
app, err := client.GetApp(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Connected to app: %s\n", app.Name)
}

Every SDK method is a direct call on the client — no nested service namespaces. The Go variant is context-aware on every method so callers can cancel, deadline, or trace any request.

An index is an app-scoped RAG container — what other ecosystems call a “vector store.” Documents inside an index get chunked, embedded, and become searchable by meaning. (Customer file blobs and structured records belong in your backend — Tavora is the agent layer, not a storage layer.)

index, err := client.CreateIndex(ctx, tavora.CreateIndexInput{
Name: "Support docs",
Description: "FAQ and product manuals",
})
if err != nil {
log.Fatal(err)
}
doc, err := client.UploadDocument(ctx, tavora.UploadDocumentInput{
IndexID: index.ID,
FilePath: "./faq.md",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Uploaded %s (status: %s)\n", doc.ID, doc.Status)

Embedding runs in the background. Poll getDocument until status === "ready" before searching — or just upload and search a moment later in dev.

results, err := client.Search(ctx, tavora.SearchInput{
Query: "what document formats are supported?",
IndexID: index.ID,
Limit: 5,
})
if err != nil {
log.Fatal(err)
}
for _, r := range results {
fmt.Printf("%.2f%s\n", r.Score, r.Snippet)
}

Default search returns one row per matched chunk. Use searchDocuments when the agent’s question is “what artifacts are about X” rather than “what passages are about X” — same call, server- deduped to one row per document with the best chunk inlined.

Agent sessions are the canonical path for anything that needs reasoning, tool use, or multi-step work. One session = one ongoing conversation; each turn runs the LLM, which writes JS that executes in the Goja sandbox where it can search, fetch, ai, remember, require('<mcp-server>'), and more.

session, err := client.CreateAgentSession(ctx, tavora.CreateAgentSessionInput{
Title: "First agent chat",
SystemPrompt: "You are a helpful assistant. Use think for " +
"computation or multi-step work.",
})
if err != nil {
log.Fatal(err)
}
err = client.RunAgent(ctx, session.ID, "Summarise my FAQ in 3 bullets.",
func(evt tavora.AgentEvent) {
switch evt.Type {
case tavora.EventTypeExecuteJS:
fmt.Printf("[js] %s\n", evt.Content)
case tavora.EventTypeResponse:
fmt.Printf("\n%s\n", evt.Content)
case tavora.EventTypeDone:
if evt.Summary != nil && evt.Summary.Tokens != nil {
fmt.Printf("[%d steps, %d+%d tokens]\n",
evt.Summary.Steps,
evt.Summary.Tokens.Prompt,
evt.Summary.Tokens.Completion)
}
}
})
if err != nil {
log.Fatal(err)
}

runAgent streams SSE events: execute_js, execute_js_result, tool_call, tool_result, sandbox_event, response, input_request, done. Reuse the same session.id across turns to keep conversation history.

The session above ran an ad-hoc agent (inline Title + SystemPrompt). For production, author the agent under a local tavora/ folder and ship with tavora deploy; your runtime then just passes AgentID to CreateAgentSession. See the tavora CLI for the init / dev / deploy loop.

  • Go & TS SDKs overview — full method catalogue.
  • MCP servers — declare your domain API in agent.jsonc → mcp so the agent can call your tools.
  • Browser-based chat — let a browser call the SDK directly via session-minted keys.
  • Skillsrequire()-able JS modules and prompt skills authored as files under your agent’s folder.
  • REST API — when the SDK isn’t an option.