Scalekit tool tracing
Trace Scalekit Node.js executeTool calls as tool spans in Future AGI without recording account identifiers or payloads.
Trace each scalekit.tools.executeTool() call as a tool span under your application’s active agent span in Future AGI. Scalekit’s Node SDK does not emit these spans itself; this example instruments the application boundary, not a second wrapper around the same call.
Install
Use Node.js 18.19+ or 20.6+ (not Node 19) and @scalekit-sdk/node 2.5.0 or later. The example also works with the current 2.21.0 SDK; earlier 2.x versions did not expose tools.executeTool().
npm install @scalekit-sdk/node@^2.5.0 @traceai/fi-core@^1.1.0 @opentelemetry/api@^1.9.0 @opentelemetry/context-async-hooks@^2.0.1
Create an Observe project and set the keys from API keys. Keep the Scalekit client secret on the server; never put it in browser code.
export FI_API_KEY="your-future-agi-api-key"
export FI_SECRET_KEY="your-future-agi-secret-key"
export FI_PROJECT_NAME="scalekit-tools"
export SCALEKIT_ENV_URL="your-scalekit-environment-url"
export SCALEKIT_CLIENT_ID="your-scalekit-client-id"
export SCALEKIT_CLIENT_SECRET="your-scalekit-client-secret"
The Future AGI provider sends OTLP/HTTP traces to https://api.futureagi.com/tracer/v1/traces with both Future AGI keys. For self-hosted Future AGI, set FI_BASE_URL to its origin (without /tracer/v1/traces).
Trace a tool call
In your server application, register a provider once before running your agent, then trace the call at the place where your code awaits it:
import { Scalekit } from "@scalekit-sdk/node";
import { register, ProjectType } from "@traceai/fi-core";
import { context, SpanStatusCode } from "@opentelemetry/api";
import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
// If the app already configured an OpenTelemetry context manager, keep it.
const manager = new AsyncLocalStorageContextManager().enable();
if (!context.setGlobalContextManager(manager)) manager.disable();
const provider = register({
projectName: process.env.FI_PROJECT_NAME,
projectType: ProjectType.OBSERVE,
});
const tracer = provider.getTracer("scalekit-tool-boundary");
const scalekit = new Scalekit(
process.env.SCALEKIT_ENV_URL,
process.env.SCALEKIT_CLIENT_ID,
process.env.SCALEKIT_CLIENT_SECRET,
);
async function executeScalekitTool({ toolName, connectedAccountId, params }) {
return tracer.startActiveSpan(`execute_tool ${toolName}`, async (span) => {
span.setAttribute("fi.span.kind", "TOOL");
span.setAttribute("tool.name", toolName);
try {
const response = await scalekit.tools.executeTool({
toolName, connectedAccountId, params,
});
// Scalekit returns arbitrary tool-specific data; adapt this predicate to
// your tool's response schema. A resolved failure is not an exception.
if (response.data?.success === false) {
span.setStatus({ code: SpanStatusCode.ERROR });
} else {
span.setStatus({ code: SpanStatusCode.OK });
}
return response;
} catch (error) {
// Do not attach error.message or stack: they may contain user data.
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
});
}
// Call executeScalekitTool() inside your active agent operation with the
// tool name, connected account ID, and parameters from your tool's schema.
// For a one-shot process, call await provider.shutdown() after the agent ends.
@traceai/fi-core 1.1.0 exports each span on completion through a SimpleSpanProcessor. Its batch: true option does not activate batching with OpenTelemetry SDK 2.x; do not rely on it for bursty production traffic. The default OTLP exporter allows 30 concurrent exports, so a slow collector can cause additional tool spans to be dropped. For sustained or bursty traffic, configure your existing OpenTelemetry SDK provider with a BatchSpanProcessor and an OTLP/HTTP exporter instead, preserving the Future AGI endpoint, API-key headers and Observe project resource attributes. Do not register both providers. For low-volume use of this example, keep the collector responsive and monitor for dropped exports.
Use listTools() to find the available tool name and its required parameters, then call executeScalekitTool({ toolName, connectedAccountId, params }) from your agent’s existing trace context. Scalekit returns data and executionId; data has no universal success field. The success === false check illustrates a tool whose payload uses that field: replace it with your tool’s documented failure predicate so a resolved business error is marked as an error too. A thrown SDK/transport error is rethrown unchanged after marking the span.
Open Observe, choose scalekit-tools (or your FI_PROJECT_NAME), and open the trace containing the tool call. If you already have an OpenTelemetry provider and async context manager, use that provider’s tracer and exporter; do not call register() or install a second context manager. Do not wrap executeTool() twice.
Warning
The tool span adds only the tool name, kind and error status, not tool arguments, results, connected-account IDs, credentials, execution IDs or exception messages. register() can still attach host/process details as resource attributes; use a provider with resource detection disabled or a redacting collector if those details are sensitive. Tool names can still disclose business operations; restrict names or redact them before exporting if needed. Your own agent or HTTP instrumentation can record additional fields independently. Do not assume FI_HIDE_INPUTS or FI_HIDE_ERROR_DETAILS sanitizes spans created with the standard OpenTelemetry API.
Questions & Discussion