Skip to content

Custom Tool

Objective: define a tool that updates shared state and returns structured data.

import type { AgentActionSession } from "@harness-kernel/core/agent/session";
import { HarnessTool } from "@harness-kernel/core/agent/tool";
import { s, type InferInput } from "@harness-kernel/core/schema";
const rememberSchema = s.object({
note: s.string().min(1),
});
type RememberInput = InferInput<typeof rememberSchema>;
class RememberNoteTool extends HarnessTool<RememberInput, { count: number }> {
name = "remember_note";
description = "Remember a note in shared state.";
schema = rememberSchema;
risk = "write" as const;
requiresApproval = true;
async execute(args: RememberInput, session: AgentActionSession) {
const input = rememberSchema.parse(args);
const state = session.state.get();
const notes = Array.isArray(state.notes) ? state.notes : [];
const next = [...notes, input.note];
session.state.update({ notes: next });
return {
content: `Remembered ${input.note}`,
data: { count: next.length },
metadata: { stateKey: "notes" },
};
}
}

Attach it to a mode:

class NotesMode extends HarnessMode {
tools = [new RememberNoteTool()];
}

Boundary note: the tool belongs to a mode. The runtime host still decides approval policy and sandbox access.

To return a recoverable structured failure:

import { createToolErrorResult } from "@harness-kernel/core/agent/tool";
return createToolErrorResult({
code: "tool.failed",
message: "The note already exists.",
toolName: this.name,
});

Thrown exceptions are also converted to AgentToolResult.isError, but returning a structured failure gives the model a cleaner recovery signal.

API: Tools and Tool Schemas.