Sapior LogoSapior

I built an open-source AI Jobs Agent using Amazon Bedrock AgentCore and AWS serverless

A production-style job discovery agent that collects posts, scores them against a candidate profile, and sends matched alerts—built on Bedrock AgentCore, Lambda, DynamoDB, and EventBridge, and released as open source.

Why another jobs tool?

Job boards are good at keyword search and bad at context. You still end up pasting the same resume into ten forms and reading JDs that look close but aren't. I wanted an agent that would act like a patient first-pass recruiter: pull in new roles, reason about fit against my actual skills, and only interrupt me when there was a strong reason.

The result is an open-source AI Jobs Agent built on Amazon Bedrock AgentCore and AWS serverless. It is not a startup. It is a focused utility: an event-driven pipeline that watches job sources, deduplicates posts, matches them with a stored candidate profile, and sends a daily email with the top opportunities.

Why Bedrock AgentCore instead of hand-rolling an agent loop

Most AI agents fail in the same places: state management, tool retries, memory, and guardrails. I did not want to build another LangChain loop that loses context after three tool calls.

[Amazon Bedrock AgentCore](https://aws.amazon.com/bedrock/agentcore/) is AWS's managed runtime for building and operating agents. It handles orchestration, memory, and tool use while keeping model access through Bedrock. That gave me a cleaner separation: the agent only needed a system prompt, a small set of tools, and an evaluation path.

With AgentCore, I defined one agent with three tools:

`search_jobs` — query the collected job index from DynamoDB.

`score_fit` — compare a job description against a stored candidate profile.

`send_alert` — create an SNS/SES message for high-scoring roles.

The agent uses those tools in a loop. If a job is ambiguous, it can call `get_job` for the full text. If a match is borderline, it writes a short rationale instead of silently discarding it.

The serverless architecture

The pipeline is fully serverless:

**[Amazon EventBridge Scheduler](https://docs.aws.amazon.com/scheduler/latest/UserGuide/what-is-scheduler.html)** triggers a collection Lambda every 30 minutes.

**[AWS Lambda](https://aws.amazon.com/lambda/)** pulls from configured job source adapters—RSS, JSON APIs, and one Greenhouse board client—and writes raw posts to S3.

**[Amazon DynamoDB](https://aws.amazon.com/dynamodb/)** stores jobs, dedupe keys, candidate profile, and match history.

**[Amazon Bedrock AgentCore](https://aws.amazon.com/bedrock/agentcore/)** runs the agent when new jobs are normalized.

**Amazon SNS + Amazon SES** sends the digest.

**Amazon API Gateway** exposes a small dashboard for manual review.

The flow is:

1. Scheduler invokes `collect-jobs`.

2. `collect-jobs` normalizes the posts and writes new jobs to the `jobs` table.

3. A DynamoDB stream triggers `match-new-jobs`.

4. `match-new-jobs` invokes the Bedrock AgentCore agent with the batch of new job IDs.

5. The agent scores each job and writes match records.

6. High-confidence matches emit an event for the notifier.

All of this is defined in AWS CDK. The agent, tools, and guardrails ship as infrastructure, not as a separate Python package with environment variables.

Matching quality is an evaluation problem, not a prompt problem

The most important decision was to make scoring deterministic enough to evaluate. The agent must return JSON with:

`relevance_score` from 0 to 10.

`required_skill_matches`.

`missing_skills`.

`concerns`.

`recommended_action`.

That structured output is evaluated nightly against a small set of labeled jobs. Bedrock AgentCore makes the agent reproducible, but the quality still comes from reviewing false positives. I care more about precision than recall here. A single bad email trains me to ignore the agent.

To reduce noise, the system uses two thresholds. Above 8.0, it alerts immediately. Between 6.5 and 7.9, it stores matches in a weekly digest. Below that, it does not surface the job.

Guardrails and safety for a jobs agent

Agent guardrails matter even for a small utility. The agent should not invent jobs, should not send email to arbitrary addresses, and should not use the candidate profile outside the matching context.

I configured Bedrock Guardrails with a denied topic for fabricated job listings and a sensitive-information filter for personal email and phone. The `send_alert` tool requires a verified recipient ID stored in DynamoDB. If the agent tries to pass a free-text address, the tool returns an error and the agent has to stop.

Why serverless was the right default

This agent spends most of its time waiting. Job sources change slowly. Serverless matches that pattern exactly: no idle EC2 instances, no container orchestrator, and no stateful agent server to patch.

The trade-off is cold starts. A tool call from AgentCore to a cold Lambda can add a few hundred milliseconds. In a batch of 30 jobs, that isn't material. I kept the functions small and ARM-based. If sub-second single-job matching ever matters, I can move the scoring Lambda to provisioned concurrency for specific hours.

Cost is equally boring: a personal deployment with a compact model stays in the single-digit dollars per month range. The scheduler, Lambda, DynamoDB, and SNS usage is negligible. Bedrock tokens are the only line item worth watching.

Open source and local development

The repo is open source with an MIT license. It includes:

CDK app for all infrastructure.

Lambda source for collectors, normalizers, and notifier.

Agent prompt and tool definitions.

Guardrail configuration.

Local test harness using recorded Bedrock responses.

Example job source adapters.

I avoided making the local environment depend on AWS credentials for basic prompt iteration. The harness can run the same JSON scoring function against fixture data. That means agent prompt changes are reviewable before touching a real model.

What I would do differently

If I were starting over, I would invest earlier in evaluation fixtures. The prompt is easy to change; the regression examples are the real product.

I would also spend less time on general job board ingestion. Maintaining ten source adapters is not valuable for one person. Two or three high-signal sources are better than a broad crawl.

Finally, I would keep the agent small. The more tools I added, the more the agent used them defensively instead of answering the question. A focused agent with strict JSON output beats a general career assistant.

The smallest useful version

You do not need vector databases, multi-agent debate, or a browser agent to solve this. The smallest useful system is:

A scheduled job fetcher.

A durable job list.

A stored candidate profile.

A managed agent loop with a scoring tool.

An email notifier with a threshold.

That is exactly what this project is. The CDK stack is open source and deployable. Replace the candidate profile with your own, point it at two or three job sources, and let the agent do the first-pass filtering.

I Built an Open-Source AI Jobs Agent with Amazon Bedrock AgentCore and AWS Serverless