{"slug": "real-world-project-a-posting-collection-analysis-agent-from-start-to-finish", "title": "Real-World Project: A Posting Collection & Analysis Agent from Start to Finish", "summary": "A developer has published a field guide chapter detailing a daily-running autonomous agent, built with Claude Code, that collects contest and grant postings, filters out risky clauses, and produces a one-page morning digest. The system enforces a three-part checklist before recommending anything to a human — whether entries are open, whether the user is eligible, and whether the terms are safe — after an earlier version reported an already-closed contest as a participation candidate. The developer argues that writing tests first narrows an AI's scope of work from 'make something reasonably good' to 'make these tests pass,' and that failures must be surfaced alongside successes for the report to be trusted.", "body_md": "*This is chapter 8 of my book **Building Autonomous AI Agents with Claude Code** — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*\n\n\"Automatically collect contest and grant-program postings every day, filter out risky clauses, and produce\n\na one-page report to read in the morning.\"\n\nThe input (posting sites), processing (parsing and filtering), output (digest), and schedule (every morning) are all in one sentence.\n\nWhen you hand work to an AI, this sentence becomes **both the work order and the completion criterion**. If it's fuzzy,\n\nthe AI will very quickly build \"something plausible that isn't what I wanted.\"\n\nThe first prompt handed to the agent looks like this.\n\n**If you don't write the \"completion criterion,\" the AI's definition of done is \"I finished writing the code.\"** The done we want is\n\n\"it runs.\" This two-line difference is also why the auditor from Chapter 6 is needed.\n\nThe AI will plausibly guess, \"that site usually has this kind of structure.\" **A parser built from that guess is always wrong.** Enforce the order.\n\n```\ncurl -sL \"https://example.org/contest/list\" -o /tmp/list.html\ngrep -o 'class=\"[a-z_-]*\"' /tmp/list.html | sort | uniq -c | sort -rn | head -20\n```\n\nMeasuring reveals things you could never know from guessing.\n\nThe third one is a failure we actually experienced. Without parsing the closed/open status, we assumed \"it's on the list, so it's still open\"\n\nand **reported a contest that had already ended as a participation candidate.** We were verifying the hard things like eligibility and terms\n\nwhile missing the most basic question: \"is it accepting entries right now?\" So this rule is now baked into the collector.\n\n**Checklist before recommending anything to a human: ① Is it accepting entries? ② Are we eligible? ③ Are the terms safe? Only something that passes all three is a candidate.**\n\nFreeze the HTML fragments confirmed during measurement directly into test fixtures. Even if the site changes later,\n\nthese tests guard against regressions in **the parser logic itself**.\n\n```\n# tests/test_collector.py\nSAMPLE = \"\"\"\n<div class=\"list-item\">\n</div>\n<div class=\"list-item\">\n</div>\n\"\"\"\n\ndef test_only_open_contests_are_collected():\n    items = parse_list(SAMPLE)\n\ndef test_deadline_is_extracted():\n    assert parse_list(SAMPLE)[0][\"deadline\"] == \"2026-09-18\"\n```\n\nWriting tests first narrows the AI's scope of work. Instead of \"make something reasonably good,\" it becomes\n\n**\"make these tests pass.\"** This is the strongest form of control you have when delegating work to an AI.\n\nKeep the collector as independent modules per source, so that if one dies the rest keep running.\n\n**In exchange, a dead source must always appear in the report.**\n\n``` python\ndef collect_all(sources):\n    results, failures = [], []\n    for name, fn in sources.items():\n        try:\n            items = fn()\n            results.extend(items)\n            failures.append(f\"{name}: {type(e).__name__} {e}\")\n    return results, failures\n```\n\nAnd the top of the report starts like this.\n\nA system that only shows success counts cannot be trusted. **Failures must appear on the same line** for a human to believe it.\n\nHow a single `except: pass` line quietly kills a system is covered in detail in Chapter 9.\n\nThe real value of this project is not collection but **selection**. It finds risky clauses in posting terms\n\nand classifies them as risky, caution, or safe.\n\n``` python\nRISK_PATTERNS = [\n]\n\ndef judge(text):\n    hits = [(level, why) for pat, level, why in RISK_PATTERNS\n            if re.search(pat, text)]\n```\n\nYour domain surely has a \"pre-participation checklist\" like this too. Toxic contract clauses, a client's creditworthiness,\n\ndelivery terms — whatever it is, **the moment you move the checklist from your head into code, mistakes are structurally blocked.**\n\nA tired human skips steps; a regex never does.\n\nWhen putting it on the scheduler, follow the rules from Chapter 7 (English-only paths end to end + the wrapper chain) exactly.\n\nThen hand verification to the **independent auditor** (Chapter 6) along with the goal sentence. In practice, the auditor\n\ncaught \"it was only registered and never actually executed once,\" and the cross-AI review got the RSS parsing\n\nchanged from regex to a standard XML parser. **Working alone, I would have missed both.**\n\n| Time | Who | What | \n|---|---|---|\n| 09:30 | System | Collect → filter → generate digest | \n| 2 min in the morning | Human | Check new items (🆕) and the **failures section** | \n| 5 min in the morning | Human | Run the terms filter only on postings of interest, then decide whether to participate | \n\nThe system does the collecting and selecting; the human only makes **decisions**. That division of labor is the target state of an autonomous agent.\n\n| Field | Collection target | Risky clauses (filter) | Output | \n|---|---|---|---|\n| Freelancing | Outsourcing postings | Unlimited revisions, full IP transfer | 3 gigs to apply for | \n| Job hunting | Job postings | Inclusive-wage clauses, probation pay cuts | Application candidates | \n| Real estate | Listings | Existing mortgages, special conditions | Site-visit candidates | \n| Development | Release notes | Breaking changes | Upgrade caution list | \n\nThe only things that change are the parser and the regexes; **the skeleton (measure → fixtures → independent modules → visible failures → audit) stays the same.** Build this skeleton once, and the next agent takes half a day.\n\n**Want the whole system?** The book has 10 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: [https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code](https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code)\n\nNot sure yet? The first three chapters are free, same PDF format: [https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample](https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample)\n\nQuestions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.", "url": "https://wpnews.pro/news/real-world-project-a-posting-collection-analysis-agent-from-start-to-finish", "canonical_source": "https://dev.to/dbsoul/real-world-project-a-posting-collection-analysis-agent-from-start-to-finish-1g2j", "published_at": "2026-09-11 04:10:06+00:00", "updated_at": "2026-09-11 04:55:43.766021+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-products"], "entities": ["Claude Code", "Anthropic"], "alternates": {"html": "https://wpnews.pro/news/real-world-project-a-posting-collection-analysis-agent-from-start-to-finish", "markdown": "https://wpnews.pro/news/real-world-project-a-posting-collection-analysis-agent-from-start-to-finish.md", "text": "https://wpnews.pro/news/real-world-project-a-posting-collection-analysis-agent-from-start-to-finish.txt", "jsonld": "https://wpnews.pro/news/real-world-project-a-posting-collection-analysis-agent-from-start-to-finish.jsonld"}}