Skip to main content

Pick your starting point

Two paths — both use the same query() function.

Path 1 — With a GitAgent repo URL

import { query } from "@open-gitagent/gitagent";

for await (const msg of query({
  repo: "https://github.com/your-gitagent",
  prompt: "Summarise the open pull requests",
})) {
  if (msg.type === "assistant") console.log(msg.content);
}
GitAgent clones the repo, reads agent.yaml + SOUL.md + skills. Zero config — the repo is your agent.

Path 2 — Without a repo

import { query } from "@open-gitagent/gitagent";

for await (const msg of query({
  prompt: "Refactor the auth module in src/auth.ts",
  model: "anthropic:claude-sonnet-4-6",
  dir: "./my-project",
})) {
  if (msg.type === "assistant") console.log(msg.content);
}
Pure SDK — point at an existing directory. No agent repo needed. Ideal for embedding in an app you already have.

API Reference

query()

import { query } from "@open-gitagent/gitagent";

for await (const msg of query({
  prompt: "Refactor the auth module",
  dir: "/path/to/agent",
  model: "anthropic:claude-sonnet-4-6",
})) {
  switch (msg.type) {
    case "delta":       // streaming text chunk
      process.stdout.write(msg.content); break;
    case "assistant":   // complete response
      console.log(`\nTokens: ${msg.usage?.totalTokens}`); break;
    case "tool_use":    // tool invocation
      console.log(`Tool: ${msg.toolName}(${JSON.stringify(msg.args)})`); break;
    case "tool_result": // tool output
      console.log(`Result: ${msg.content}`); break;
    case "system":      // lifecycle events & errors
      console.log(`[${msg.subtype}] ${msg.content}`); break;
  }
}

tool()

import { query, tool } from "@open-gitagent/gitagent";

const search = tool(
  "search_docs",
  "Search the documentation",
  {
    properties: {
      query: { type: "string", description: "Search query" },
      limit: { type: "number", description: "Max results" },
    },
    required: ["query"],
  },
  async (args) => {
    const results = await mySearchEngine(args.query, args.limit ?? 10);
    return { text: JSON.stringify(results), details: { count: results.length } };
  },
);

for await (const msg of query({ prompt: "Find auth docs", tools: [search] })) {
  // agent can now call search_docs
}

buildTool()

import { buildTool } from "@open-gitagent/gitagent";

const myTool = buildTool({
  name: "search_docs",
  description: "Search documentation",
  parameters: {
    properties: { query: { type: "string" } },
    required: ["query"],
  },
  execute: async (args) => {
    return "Results: ...";
  },
  metadata: {
    isConcurrencySafe: true,   // safe to run in parallel
    isReadOnly: true,           // no side effects
    maxResultSizeChars: 20000,  // truncate large results
  },
});

hooks

const result = query({
  prompt: "Deploy to production",
  dir: "/path/to/agent",
  hooks: {
    onSessionStart: async (ctx) => ({ action: "allow" }),
    preToolUse: async (ctx) => {
      if (ctx.toolName === "cli" && ctx.args.command.includes("deploy")) {
        return { action: "block", reason: "Manual approval required" };
      }
      return { action: "allow" };
    },
    postToolFailure: async (ctx) => {
      console.error(`Tool ${ctx.toolName} failed: ${ctx.error}`);
    },
    preQuery: async (ctx) => {
      console.log(`Sending prompt to LLM: ${ctx.sessionId}`);
      return { action: "allow" };
    },
    postResponse: async (ctx) => {
      console.log(`Session ${ctx.sessionId} responded`);
    },
    fileChanged: async (ctx) => {
      console.log(`File changed: ${ctx.path}`);
    },
    onError: async (ctx) => {
      console.error(`Error in ${ctx.sessionId}: ${ctx.error}`);
    },
  },
});
These are the same lifecycle hooks used by the Hooks capability — the SDK just lets you register them in code instead of hooks/hooks.yaml.

QueryOptions

Parameters accepted by query()
NameTypeRequiredDescription
promptstring | AsyncIterableYesUser prompt or multi-turn stream
dirstringAgent directory (default: cwd)
modelstring”provider:model-id”
envstringEnvironment config (config/<env>.yaml)
systemPromptstringOverride discovered system prompt
systemPromptSuffixstringAppend to discovered system prompt
toolsGCToolDefinition[]Additional tools
replaceBuiltinToolsbooleanSkip cli/read/write/memory
allowedToolsstring[]Tool name allowlist
disallowedToolsstring[]Tool name denylist
maxTurnsnumberMax agent turns
abortControllerAbortControllerCancellation signal
constraintsobjecttemperature, maxTokens, topP, topK
hooksobjectonSessionStart, preToolUse, postToolFailure, preQuery, postResponse, fileChanged, onError lifecycle hooks
repoobjectWork on a remote git repo — clone, run agent, auto-commit changes to session branch
sandboxSandboxOptions | booleanRun agent inside an E2B cloud VM (true uses defaults)
sessionIdstringTag or resume a specific session

Message Types

Emitted by the query() async iterator
TypeFieldsDescription
deltadeltaType, contentStreaming text/thinking chunk
assistantcontent, model, usage, stopReasonComplete LLM response
tool_usetoolName, args, toolCallIdTool invocation
tool_resulttoolName, content, isError, toolCallIdTool output
systemsubtype, content, metadataLifecycle events
usercontentUser message (multi-turn)

Cost Tracking

const result = query({ prompt: "...", dir: "..." });

for await (const msg of result) { /* handle messages */ }

const costs = result.costs();
console.log(`Cost: $${costs.totalCostUsd.toFixed(4)}`);
console.log(`Tokens: ${costs.totalInputTokens} in / ${costs.totalOutputTokens} out`);
See Utilities for the full shape of the costs() result and for context-compaction helpers.

SDK Quickstart

Install the SDK and run your first query()

Utilities

Context compaction and cost tracking helpers

Telemetry

OpenTelemetry spans, metrics, and Jaeger setup

Capabilities: Tools

Built-in tools available to every agent