Building your first agent

A 30-minute walkthrough — write the prompt, spawn it, debug it, ship it.

By the end of this guide you'll have a working agent that summarizes the top story on Hacker News, learns from each run, and is ready to extend toward anything-with-a-feed.

The task

Read the front page of Hacker News. Find the top story. Return a JSON object with the title, link, and a one-sentence "why this matters" summary.

Five minutes to write, 25 minutes to iterate. Let's go.

Step 1 — Write the first version

Open a file, write this:

bash
curl -X POST https://jettson.dev/api/v1/agents \
  -H "Authorization: Bearer $JETTSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "task": "Use jettson_browser_navigate on https://news.ycombinator.com. Then jettson_browser_extract_text. Find the top story. Return JSON: {top_story: {title, link, why_it_matters}}."
  }'

Save it as run.sh, make it executable, run.

The Console (at /console/agents) shows the agent spawn, browse, extract, reason, and return — usually 6-8 seconds end to end with a warm-pool hit.

Check final_result. You'll see roughly the right answer. Probably the title is right; the link might be the relative URL item?id=... instead of the full one; "why it matters" might be too generic.

Step 2 — Tighten the prompt

The Mind is good but it's not psychic. Where the output was wrong, the prompt was vague. Iterate:

text
Use jettson_browser_navigate on https://news.ycombinator.com.
Then jettson_browser_extract_text to grab the page.

Identify the TOP story the first one listed.

For the link: Hacker News uses relative URLs like "item?id=...".
Convert it to an absolute URL: https://news.ycombinator.com/item?id=...

For "why it matters": be specific. "Talks about X and Y" is bad.
"This matters because Z" is good. One sentence, max 25 words.

Return only this JSON:
{
  "top_story": {
    "title": "...",
    "link": "...",
    "why_it_matters": "..."
  }
}

Run again. Output should be sharper.

Step 3 — Add memory

Here's where it gets fun. Tell the agent to skip stories it's already covered:

text
[the same prompt as above]

BEFORE returning, call jettson_memory_search with the story title as the query
and namespace="hn_seen".
If a memory with `score >= 0.7` exists, that means we've seen this story
before. Return: { "skipped": true, "reason": "already covered <date>" } instead.

AFTER returning a new story, call jettson_memory_put:
  - namespace: "hn_seen"
  - key: "story_<id-from-link>"
  - value: <title + summary>
  - importance: 6
  - expires_in_days: 14

Run it twice. The second run skips. Run it tomorrow on a different top story; it picks the new one and remembers it.

You've now built an agent that won't repeat itself. That's a real piece of software.

Step 4 — Debug a failure

Eventually the agent will fail. Maybe Hacker News changes its HTML; maybe the timeout fires; maybe the JSON it returns is malformed. Here's how to debug:

  1. Open the agent in the Console. The Progress timeline shows every thinking, tool_use, tool_result, and the final agent_completed or agent_errored.
  2. Look at the last successful tool_result. That's the last known good state. Whatever happened after it is the bug.
  3. Read the next tool_use input. If the Mind picked a weird selector, the prompt didn't constrain it enough.

Common fixes:

  • The Mind picked the wrong element → add a more specific selector hint in the prompt.
  • The browser returned truncated: true → ask for a selector argument on the extract call (e.g. tr.athing for HN's story row).
  • The JSON had extra prose around it → the prompt is letting the model preface. Add: "Return ONLY the JSON. No prose before or after."

Step 5 — Iterate

The cycle: run → check output → tighten prompt → run again. Five minutes per iteration.

Three patterns that consistently make agents better:

  1. Constrain the output shape upfront. "Return JSON with these fields." is better than "Tell me about it."
  2. Reference tools by name. "Use jettson_browser_extract_text" is better than "look at the page."
  3. Memory in, memory out. Recall before deciding; remember after deciding. That's the whole loop.

What good looks like

When you're done, the prompt is ~50 lines of Markdown. It runs in under 8 seconds. It returns valid JSON every time. It remembers what it's seen. You ship it as a cron job that emails you the top new story every morning.

You wrote it in 30 minutes.

Where to go from here