DEV Community

Cover image for Stop Starting From Scratch: Build Agents with Strands harness
Morgan Willis for AWS

Posted on Originally published at x.com AI-assisted

Stop Starting From Scratch: Build Agents with Strands harness

Getting an agent to do useful work accurately, reliably, without burning through your token budget, takes a lot more engineering work than a demo makes obvious. Everyone wants to hand over simple tasks to AI agents, but they spend more time deciding how to manage context, run tools, retain useful memory, and cache repeated input. After that, it's still not always clear how to work out whether those choices improved the agent's performance or made things worse. This is harness engineering, and there's usually a long process of trial and error before your agent goes to production.

AWS engineers have spent a lot of time building production quality agents and learning which of those decisions really improve outcomes in practice. Much of that work is the same from one agent to the next. Every agent needs a foundation for managing context, using tools, and carrying state forward, whether it maintains documentation, investigates an incident, or handles customer requests.

The latest launch from AWS, Strands harness, packages that foundation into a general-purpose agent harness you can add to your application in a few lines of code. Out of the box, you get a tuned prompt, context management, memory, tools, skills, and defaults you can replace as your use case becomes more specific. You choose the model, your instructions, your connected systems, and where the agent runs. It's model and cloud provider agnostic. It supports both Python and TypeScript.

Those defaults are more than a convenient starting point. The launch benchmarks report frontier performance with 28% lower token cost.

benchmark)

Getting this sort of performance out of the box lets you spend your time on the job your agent is actually meant to do. You bring your domain knowledge, your systems, specific requirements, and the controls your application needs.

I work at AWS, and I already used an agent on my laptop to update documentation for my small apps after changing their code. I wanted those updates to happen automatically when I merge a code change without me kicking the process off myself.

I created a docs bot agent using Strands harness and set it up to run in GitHub Actions. The code for the docs-bot can be found on GitHub if you want to follow along.

The agent I deployed using Strands harness and GitHub Actions

This is the agent code for my docs maintainer bot:

import { createHarness } from "@strands-agents/harness"
import { getTask } from "./workflow-support.js"

const docsAgent = await createHarness({
  session: { id: process.env.DOCS_SESSION_ID },
  instructions:
    "Use the docs-writing and humanize skills for documentation work. " +
    "Review code changes, or audit the implementation if no diff is supplied. " +
    "Create missing docs and update stale ones. Run every runnable example " +
    "in the docs and the project test suite. Fix documentation issues only. " +
    "Report what passed, what failed, and anything you could not verify. " +
    "Write that summary to run-output/agent-summary.md, then reply with it.",
})

const task = await getTask()

try {
  const result = await docsAgent.invoke(task, { limits: { turns: 30 } })

  if (result.stopReason !== "endTurn") {
    throw new Error(`Agent stopped: ${result.stopReason}`)
  }
} finally {
  await docsAgent.memoryManager?.flush()
}
Enter fullscreen mode Exit fullscreen mode

createHarness() creates the agent, and instructions adds the documentation job to its tuned system prompt. Most of the behavior comes from defaults that are already configured:

  • File, shell, and web tools to inspect code, edit documentation, run examples, and fetch pages.
  • Context management to summarize older turns and offload large tool results for later retrieval.
  • Prompt caching where supported to reduce the cost of repeated input.
  • Sessions and long-term memory to continue conversations and retain useful knowledge.
  • Skills, task tracking, subagents, and programmatic tool calling to guide and coordinate the work.

You can replace or disable defaults and add custom tools or MCP integrations. For this bot, I mainly needed documentation instructions and my existing writing skills.

The getTask() helper supplies the prompt that gets passed to the agent and it contains the code changes to investigate. docsAgent.invoke() starts the agent, with a limit of 30 turns. The agent updates the documentation and writes a summary for the PR description.

GitHub Actions handles the automation around it. This includes triggering the run, restoring saved state, independently checking the changes, and opening the pull request. Then I review the PR, give feedback, or merge it.

The complete example and setup instructions are in the repo.

Reuse your skills

I put the documentation writing skills I already used locally into the repository:

.agent/skills/
  docs-maintainer/SKILL.md
  docs-writing/SKILL.md
  humanize/SKILL.md
Enter fullscreen mode Exit fullscreen mode

Strands harness discovers skills in this directory without a separate registration step. The maintainer skill describes how to update and verify documentation, and the writing and humanize skills help it not put em dashes in every other sentence.

When I merge a change to my app, the docs bot kicks off and updates the usage guide and README with the new info.

Give it feedback without starting over

I usually have feedback on the documentation PR. You can leave comments on the PR and kick it back to the agent like this:

@docs-bot revise Add a short troubleshooting section explaining what happens when the input file is missing. Run the example and verify the output.
Enter fullscreen mode Exit fullscreen mode

The workflow recognizes that @docs-bot revise command and starts another run.

Strands harness supports multi-turn interactions through sessions, which preserve conversation history across runs. By default, it saves conversation history to local files organized using session IDs, which helps it keep history contained to a specific conversation. For this bot, each documentation job has its own session ID. That lets me review a PR and send the agent back to work with the context of what it already did.

The issue with using local files though is that each GitHub Actions job starts on a fresh runner, so those local files wouldn’t survive on their own. To get around this, our workflow saves them between runs, restores this PR’s conversation files, and passes the relevant session ID into createHarness(). Strands harness then loads the history automatically from those files, and my feedback becomes the next request in the saved conversation.

Strands harness also supports long-term memory using a similar local file setup. Long-term memory carries useful knowledge beyond that one conversation. For example, I might want the bot to remember that I prefer runnable examples before option tables, even when it’s working on a different PR.

Strands harness makes another model call in the background to extract these long-term memories from the conversation and saves them as Markdown files. Depending on your provider and configuration, it uses a smaller model from the same provider or reuses your main model.

Our workflow saves and restores those memory files separately from the conversation files. You can also override the local file storage that comes with Strands harness to have it use things like Amazon S3, or you can provide your own memory provider integration.

Build your own version

Strands harness gives you a highly performant and cost efficient pre-built agent harness that you can just use. It's built using the Strands Harness SDK, and when you create a harness with Strands harness, it returns a standard Strands Agent. You can change the model, extend the instructions, add tools, override any of the defaults as needed, and then deploy it anywhere. There’s also a CLI for trying configurations interactively and exporting a Python or TypeScript project.

My bot runs in GitHub Actions because that’s where my code changes happen. Yours could respond to support requests, investigate incidents, or prepare reports from your own systems.

Pick a task you want automated, build an agent for it, and share what you make!

Resources:

Top comments (0)