Invoke the agent

In shortCall client.invoke() to send messages to your agent and get back responses with full control over threading, error handling, and response structure.

  • 5 min read
  • 12 sections
  • Updated
  • v0.10.0
  • Markdown

client.invoke() sends a message to your agent and waits for the final response. It handles multiple tool calls automatically, returns full state information, and supports persistent threads so conversations can span multiple API calls. This guide walks you through the core operations.

Prerequisites

You need a configured TenxGraphClient instance and a 10xGraph API server with a compiled graph running. Set up both in Create a client first.

Build and send a message

Messages are the fundamental unit of communication with the agent. Create a message using Message.text_message(), then pass it to client.invoke() in an array:

TypeScript
import { Message, TenxGraphClient } from '10xgraph-client';

const client = new TenxGraphClient({
  baseUrl: 'http://localhost:8000',
  auth: { type: 'bearer', token: 'your-token' },
});

const response = await client.invoke([
  Message.text_message('What is the capital of France?'),
]);

The call blocks until the agent completes, including all tool calls. The return value is an InvokeResult containing the final messages array, meta (thread info), all_messages (every message across tool iterations), iterations, and optionally state, context and summary depending on response_granularity.

You can also provide a system prompt by creating a message with role 'system':

TypeScript
const response = await client.invoke([
  Message.text_message('You are a helpful geography assistant.', 'system'),
  Message.text_message('What is the capital of France?'),
]);

Extract the response text

The assistant’s response is in result.messages. Find the last message with role: 'assistant', then extract text from its content array:

TypeScript
const assistantMsg = [...response.messages].reverse().find(m => m.role === 'assistant');
if (assistantMsg) {
  const text = assistantMsg.content
    .filter(block => block.type === 'text')
    .map(block => (block as any).text)
    .join('');
  console.log(text);
}

For multimodal responses (images, audio, documents), the agent may include other block types. Check block.type to handle each one appropriately.

Keep conversation history with threads

By default, each invoke() call is independent. To maintain conversation history, pass a thread_id in the config object. The same thread will replay all prior messages in order:

TypeScript
const threadId = 'user-123-session';

// First turn
const first = await client.invoke(
  [Message.text_message('Tell me about Paris.')],
  { config: { thread_id: threadId } }
);
console.log(first.messages[first.messages.length - 1].content);

// Second turn: the agent sees the first message and response automatically
const second = await client.invoke(
  [Message.text_message('And its history?')],
  { config: { thread_id: threadId } }
);

The result includes metadata about the thread: result.meta.thread_id (the ID used) and result.meta.is_new_thread (true only on the first call for a given ID).

Control response size with granularity

The response_granularity option tells the server how much data to include in the response:

TypeScript
const response = await client.invoke(
  [Message.text_message('Summarize this document.')],
  {
    config: { thread_id: 'doc-summary-1' },
    response_granularity: 'low',  // Fastest, messages only
  }
);
Level Includes Best for
'low' Latest messages only Production chat, minimal latency
'partial' Messages + context + summary Chats that show summaries or context
'full' Messages + state Debugging, admin dashboards

In production, use 'low' for the fastest response. Move to 'partial' or 'full' only if your UI needs the extra data. The state field of the result is only filled with 'full'. The default for invoke() is 'full'.

Monitor progress with partial results

When the agent makes multiple tool calls, you can see each step with the onPartialResult callback. It fires after every iteration:

TypeScript
const response = await client.invoke(
  [Message.text_message('Research the latest breakthroughs in quantum computing.')],
  {
    onPartialResult(partial) {
      console.log(`Iteration ${partial.iteration}:`);
      console.log(`  Tool calls: ${partial.has_tool_calls}`);
      if (partial.is_final) {
        console.log('  Agent finished.');
      }
    },
  }
);
console.log(`Completed in ${response.iterations} steps.`);

The InvokePartialResult gives you iteration count, whether tool calls were made, and whether the run is complete. This is useful for showing progress bars or logging in production.

Handle errors gracefully

Network errors, authentication failures, and validation errors are thrown as exceptions. Catch TenxGraphError to handle specific HTTP status codes:

TypeScript
import { TenxGraphError } from '10xgraph-client';

try {
  const response = await client.invoke([
    Message.text_message('What is the meaning of life?'),
  ]);
  displayResponse(response.messages);
} catch (err) {
  if (err instanceof TenxGraphError) {
    switch (err.statusCode) {
      case 401:
        // Auth failed: token invalid or expired
        console.error('Not authenticated. Re-login.');
        redirectToLogin();
        break;
      case 403:
        // Auth succeeded but user lacks permission
        console.error('Permission denied for this agent.');
        break;
      case 500:
        console.error('Server error. Try again later.');
        break;
      default:
        console.error(`HTTP ${err.statusCode}: ${err.message}`);
    }
  } else {
    // Network error, timeout, etc.
    console.error('Connection failed:', err);
  }
}

See Error handling for the full error type reference.

Complete working example

This example creates a client, invokes the agent in a loop to simulate a conversation, and extracts text from each response:

TypeScript
import {
  TenxGraphClient,
  Message,
  TenxGraphError,
} from '10xgraph-client';

const client = new TenxGraphClient({
  baseUrl: 'http://localhost:8000',
  auth: { type: 'bearer', token: process.env.API_TOKEN || '' },
});

async function askAgent(
  question: string,
  threadId: string
): Promise<string | null> {
  try {
    const result = await client.invoke(
      [Message.text_message(question)],
      {
        config: { thread_id: threadId },
        response_granularity: 'low',
      }
    );

    const assistantMsg = [...result.messages].reverse().find(
      m => m.role === 'assistant'
    );
    if (!assistantMsg) return null;

    return assistantMsg.content
      .filter(block => block.type === 'text')
      .map(block => (block as any).text)
      .join('');
  } catch (err) {
    if (err instanceof TenxGraphError) {
      console.error(`Agent error [${err.statusCode}]: ${err.message}`);
    } else {
      console.error('Unexpected error:', err);
    }
    return null;
  }
}

// Example usage
(async () => {
  const thread = 'conversation-001';
  
  const answer1 = await askAgent('What is quantum entanglement?', thread);
  console.log('Agent:', answer1);

  const answer2 = await askAgent('Can you explain it more simply?', thread);
  console.log('Agent:', answer2);
})();

Compile the file to JavaScript with your usual TypeScript setup and run it with node.

Verify the setup

If you see these errors, here are the fixes:

Error Cause Fix
TypeError: Failed to fetch Server not running Start it with 10xgraph api
TenxGraphError 401 Token invalid or missing Check API_TOKEN env var
Empty messages array Agent has no output Check the agent code for issues

The agent should respond within seconds. If responses take too long, check the graph’s tool calls and model configuration.

What you learned

  • Create messages with Message.text_message() and pass them to client.invoke().
  • Extract text from the response by filtering for role === 'assistant' and block.type === 'text'.
  • Use thread_id in the config to persist conversation history across calls.
  • Set response_granularity to ‘low’ for production, ‘full’ for debugging.
  • Monitor progress with onPartialResult callbacks for multi-step agent runs.
  • Catch TenxGraphError by status code to handle auth, permission, and server errors.

Next steps

Frequently asked questions

How do I keep conversation history between calls?
Pass a thread_id in the config object. The same thread_id will replay messages in order and maintain state across multiple invoke calls, so the agent has context from earlier turns.
What's the difference between response_granularity values?
'low' returns only messages (fastest, production); 'partial' adds context and summary; 'full' adds the graph state (debugging). Use 'low' unless you need the extra data.
How do I see what the agent is doing step by step?
Pass an onPartialResult callback to invoke(). It fires after each iteration, telling you if tool calls were made and when the run completes.
Last updated for v0.10.0Edit this page on GitHubReport an issue