Skip to content

Add tools and instructions

Strands harness’s built-in contract already handles how the agent behaves; your instructions tell it who it is and what it is for, and your tools give it the capabilities your application needs. Both add to the built-ins rather than replacing them.

You tell the agent who it is with instructions, a domain block appended after the built-in contract: the agent’s identity, scope, and any rules you want it to follow. The harness’s contract handles the general “how to act like an agent” behavior, so keep instructions to what is specific to your use case.

from strands_harness import create_harness
agent = create_harness(
instructions="You are a support assistant. Always link the ticket you acted on.",
)

If you pass a full system_prompt through to the Agent instead, instructions is ignored: the prompt you supply replaces the contract entirely. To build on the contract programmatically, see compose with the Strands Harness SDK.

You give the agent your own capabilities by passing tools, which sit alongside the built-in ones. Define them the same way you would for any Strands agent:

from strands import tool
from strands_harness import create_harness
@tool
def get_ticket(ticket_id: str) -> str:
"""Fetch a support ticket by id."""
return f"Ticket {ticket_id}: open, assigned to support."
agent = create_harness(
instructions="You are a support assistant. Always link the ticket.",
tools=[get_ticket],
)

A tool name must be unique across every source (built-in tools, tools, and plugin-vended tools). A collision fails at construction and names the two sources, so nothing silently disappears. To reuse a built-in’s name, drop the built-in first.

The built-in tools are shell, read, write, edit, web_fetch, web_search, programmatic_tool_caller, and subagent, all on by default. Pass builtin_tools a subset to narrow the set, or an empty list to turn them all off and bring your own:

from strands_harness import create_harness
agent = create_harness(builtin_tools=["read", "shell"]) # just these two; [] for none

An unknown name fails at construction with the list of valid names. For what each tool does, see shell and file tools, web access, and programmatic tool calling.

web_fetch answers over a fetched page using a small, fast summarizer model chosen for your main provider so credentials line up. Override it with {"web_fetch": {"model": ...}} in builtin_tools, which takes the same forms as model. This is covered on the web access page.

For the full option list, see the configuration reference.