The @contextcompany/custom package provides full control over instrumentation for AI agents that don’t use standard frameworks. It supports two patterns: builder pattern (instrument as you go) and factory pattern (send pre-built data).
Installation
npm install @contextcompany/custom
Quick Start
Builder Pattern
Factory Pattern
import { run } from '@contextcompany/custom' ;
const r = run ({ sessionId: 'session_123' });
r . prompt ( 'What is the weather in SF?' );
// Create a step for LLM call
const s = r . step ();
s . prompt ( JSON . stringify ( messages ));
s . response ( assistantContent );
s . model ( 'gpt-4o' );
s . tokens ({ uncached: 120 , cached: 30 , completion: 45 });
s . end ();
r . response ( '72°F and sunny.' );
await r . end ();
import { sendRun } from '@contextcompany/custom' ;
await sendRun ({
prompt: { user_prompt: 'What is the weather in SF?' },
response: '72°F and sunny.' ,
startTime: new Date ( '2025-01-01T00:00:00Z' ),
endTime: new Date ( '2025-01-01T00:00:01Z' ),
steps: [{
prompt: JSON . stringify ( messages ),
response: assistantContent ,
model: 'gpt-4o' ,
tokens: { uncached: 120 , cached: 30 , completion: 45 },
startTime: new Date ( '2025-01-01T00:00:00Z' ),
endTime: new Date ( '2025-01-01T00:00:01Z' ),
}],
});
Configuration
Set global SDK options that apply to all runs.
function configure ( options : ClientConfig ) : void
API key for authentication. Overrides TCC_API_KEY environment variable. Keys starting with dev_ automatically route to development endpoint.
Enable debug logging to console. Overrides TCC_DEBUG environment variable.
Custom ingestion endpoint URL. Overrides TCC_URL environment variable.
Default auto-flush timeout (in milliseconds) for all new runs. Default: 1,200,000 (20 minutes). Can be overridden per-run.
Example:
import { configure } from '@contextcompany/custom' ;
configure ({
apiKey: 'tcc_abc123' ,
debug: true ,
runTimeout: 600000 , // 10 minutes
});
Builder Pattern API
run
Create a new Run builder. This is the main entry point for incremental instrumentation.
function run ( options ?: RunOptions ) : Run
Custom run identifier. Defaults to a random UUID.
Group multiple runs into a logical session (e.g., a single user conversation). Runs sharing a sessionId appear together in the dashboard timeline.
Mark this run as part of a multi-turn conversation. When true, the dashboard links sequential runs in the same session.
Override the run start time. Defaults to new Date().
Auto-flush timeout in milliseconds. If the run is not ended within this duration, it will be automatically flushed with an error status. Set to 0 to disable. Default: 1,200,000 (20 minutes).
A Run builder instance with the following methods.
Run Methods
prompt
Set the user prompt/input that initiated the run.
run . prompt ( input : string | { user_prompt: string ; system_prompt ?: string }): Run
User prompt as a string, or an object with user_prompt and optional system_prompt.
Example:
r . prompt ( 'What is the weather?' );
// or
r . prompt ({
user_prompt: 'Summarize this' ,
system_prompt: 'You are a helpful assistant.'
});
response
Set the agent’s final response to the user.
run . response ( text : string ): Run
Attach arbitrary key-value metadata to the run. Multiple calls are merged together.
run . metadata ( ... entries : Record < string , string > []): Run
entries
Record<string, string>[]
required
One or more metadata objects to merge. Values must be strings.
Example:
r . metadata ({ agent: 'weather-bot' , version: '1.2.0' });
status
Set the outcome status code and optional message.
run . status ( code : number , message ?: string ): Run
Status code: 0 for success, 2 for error.
Human-readable status message (e.g., error description).
endTime
Override the run’s end time (defaults to automatic capture when .end() is called).
run . endTime ( date : Date ): Run
step
Create a new Step attached to this run.
run . step ( stepIdOrOptions ?: string | StepOptions ): Step
A custom step ID string, or a StepOptions object. Omit to auto-generate an ID.
Create a new ToolCall attached to this run.
run . toolCall ( nameOrOptions ?: string | ToolCallOptions ): ToolCall
A tool name string, or a ToolCallOptions object.
end
Finalize the run and send the payload (including all attached steps and tool calls) in a single batch request.
await run . end (): Promise < void >
Throws if:
The run has already been ended
.prompt() was not called
Any attached steps or tool calls have not been ended
error
End the run with error status (2) and send the payload. Any un-ended child steps and tool calls are automatically marked as errored.
await run . error ( message ?: string ): Promise < void >
Step Methods
A Step represents a single LLM invocation within a Run.
prompt
Set the prompt sent to the LLM.
step . prompt ( text : string ): Step
The prompt text (typically serialized messages).
response
Set the LLM’s response text.
step . response ( text : string ): Step
The response text from the LLM.
model
Set the model used for this step.
step . model ( config : string | { requested? : string ; used ?: string }): Step
Pass a string when requested and used model are the same, or an object to distinguish them.
Example:
s . model ( 'gpt-4o' );
// or
s . model ({ requested: 'gpt-4o' , used: 'gpt-4o-2024-08-06' });
tokens
Record token usage for this step. Multiple calls are merged.
step . tokens ( usage : TokenUsage ): Step
Number of prompt tokens that were not served from cache.
Number of prompt tokens served from cache (e.g., prompt caching).
Number of tokens generated by the model in the completion.
Example:
s . tokens ({ uncached: 120 , cached: 30 , completion: 45 });
cost
Set the actual cost of this step in USD.
step . cost ( amount : number ): Step
finishReason
Set the model’s finish/stop reason.
step . finishReason ( reason : string ): Step
Finish reason (e.g., "stop", "length", "tool_calls").
Set the tool definitions/function schemas available to the model during this step.
step . toolDefinitions ( defs : string | unknown []): Step
defs
string | unknown[]
required
A JSON string or an array of tool definition objects (auto-serialized).
status
Set the outcome status code and optional message.
step . status ( code : number , message ?: string ): Step
Status code: 0 for success, 2 for error.
endTime
Override the step’s end time.
step . endTime ( date : Date ): Step
end
Finalize this step. Both .prompt() and .response() must have been called.
Throws if the step has already been ended, or if .prompt() or .response() was not called.
error
Mark this step as errored (status code 2).
step . error ( message ?: string ): void
A ToolCall represents a single tool/function invocation within a Run.
name
Set the tool name.
toolCall . name ( toolName : string ): ToolCall
The tool name (e.g., "search", "get_weather").
args
Set the arguments passed to the tool.
toolCall . args ( value : string | Record < string , unknown > ): ToolCall
A JSON string or a plain object (auto-serialized).
Example:
tc . args ({ city: 'San Francisco' });
result
Set the return value from the tool.
toolCall . result ( value : string | Record < string , unknown > ): ToolCall
A JSON string or a plain object (auto-serialized).
Example:
tc . result ({ temp: 72 , unit: 'F' });
status
Set the outcome status code and optional message.
toolCall . status ( code : number , message ?: string ): ToolCall
endTime
Override the tool call’s end time.
toolCall . endTime ( date : Date ): ToolCall
end
Finalize this tool call. A tool name must have been set.
Throws if the tool call has already been ended, or if no tool name was set.
error
Mark this tool call as errored (status code 2).
toolCall . error ( message ?: string ): void
Factory Pattern API
sendRun
Send a complete run (with optional nested steps and tool calls) in a single request. Use this when all data is already available.
async function sendRun ( input : RunInput ) : Promise < void >
Custom run identifier. Defaults to a random UUID.
Session identifier to group related runs.
Whether this run is part of a multi-turn conversation.
The user prompt/input that initiated the run. The agent’s final response.
When the run started (ISO-8601 string or Date).
When the run finished (ISO-8601 string or Date).
Outcome status code. 0 for success (default), 2 for error.
Human-readable status/error message.
Arbitrary key-value metadata.
LLM steps that occurred during the run. See StepInput .
Example:
await sendRun ({
prompt: { user_prompt: 'What \' s the weather?' },
response: '72°F in SF' ,
startTime: new Date ( '2025-01-01T00:00:00Z' ),
endTime: new Date ( '2025-01-01T00:00:01Z' ),
steps: [{
prompt: '...' ,
response: '...' ,
model: 'gpt-4o' ,
startTime: new Date ( '2025-01-01T00:00:00Z' ),
endTime: new Date ( '2025-01-01T00:00:01Z' ),
}],
});
sendStep
Send a single step independently. Requires runId.
async function sendStep ( input : StepInput & { runId : string }) : Promise < void >
input
StepInput & { runId: string }
required
The parent run identifier.
Custom step identifier. Defaults to a random UUID.
The prompt sent to the LLM.
Status code: 0 for success (default), 2 for error.
Which model was used. String or object with requested and used.
The model’s finish/stop reason.
Actual cost of this step in USD.
Tool definitions available to the model.
Example:
await sendStep ({
runId: 'run_abc' ,
prompt: '...' ,
response: '...' ,
model: 'gpt-4o' ,
startTime: new Date (),
endTime: new Date (),
});
Send a single tool call independently. Requires runId.
async function sendToolCall ( input : ToolCallInput & { runId : string }) : Promise < void >
input
ToolCallInput & { runId: string }
required
The parent run identifier.
Custom tool call identifier. Defaults to a random UUID.
The name of the tool that was invoked.
When the tool call started.
When the tool call finished.
Status code: 0 for success (default), 2 for error.
args
string | Record<string, unknown>
Arguments passed to the tool.
result
string | Record<string, unknown>
Return value from the tool.
Example:
await sendToolCall ({
runId: 'run_abc' ,
name: 'search' ,
args: { query: 'weather' },
result: { temp: 72 },
startTime: new Date (),
endTime: new Date (),
});
submitFeedback
Submit user feedback for a specific run.
function submitFeedback ( params : {
runId : string ;
score ?: "thumbs_up" | "thumbs_down" ;
text ?: string ;
}) : Promise < Response | undefined >
The unique identifier of the run to attach feedback to.
score
"thumbs_up" | "thumbs_down"
Feedback score as thumbs up or thumbs down.
Text feedback from the user. Maximum 2000 characters.
Environment Variables
Your Context Company API key. Get one from the dashboard .
Custom ingestion endpoint URL. Overrides the default endpoint.
Enable debug logging. Set to true or 1.
Next Steps
View Dashboard View your instrumented runs in the dashboard
Metadata Learn about adding metadata to traces