How I Turned My Job Search Into an AI-Assisted Positioning System

Apr 9, 2026 min read

I did not want to approach my job search as a vague exercise of browsing listings and improvising from there.

What I wanted was something much simpler: a way to spend time only on roles that actually fit the direction I want for my next step.

I am not trying to position myself as a generic “software engineer.” I want my next role to reinforce a more specific profile: strong systems and platform background, production AI exposure, and hands-on experience building useful tooling around LLMs and agent workflows.

That is why I built a small pipeline to collect roles, normalize them, score them against my CV, and surface the ones that are genuinely worth a closer look.

At the time of writing, the pipeline has already scraped 1,862 job documents, persisted 1,683 analyses, and produced 658 filtered roles for manual review.

The real objective was not job automation

The interesting part here is not “I automated my job search.” On its own, that is not especially interesting.

What I actually wanted was a workflow that does three things at once:

  1. Reduces the noise of large job boards.
  2. Forces explicit matching criteria instead of vague intuition.
  3. Strengthens my profile around applied AI engineering.

In practice, the system is useful because it saves me time, but it also reflects how I tend to work. If something is repetitive, fuzzy, and easy to second-guess, my instinct is usually to structure it and make the criteria visible.

A small pipeline, organized like a real application

I kept the scope small on purpose, but I still wanted the code to have clear boundaries.

At a high level, the flow looks like this:

  1. Collect public job listings from a search query.
  2. Convert each position into a clean Markdown representation.
  3. Store every job as an individual document.
  4. Send the normalized content plus my CV to an LLM analysis step.
  5. Persist the analysis results, including score, reasoning, latency, and token usage.
  6. Export the top matches into filtered folders for fast review.

diagram-explaining-architecture

The code follows a ports-and-adapters style, so scraping, storage, analysis, and logging stay separate. That might sound heavier than necessary for a personal tool, but it paid off quickly. I can change the analysis model, the output format, or the storage backend without tearing the whole thing apart.

That was intentional. Even for a side project, I wanted the implementation to look like the way I actually build software: small systems, clear responsibilities, pragmatic architecture.

Even at this scale, that structure helps. Once you are dealing with more than 1,800 scraped documents, small design decisions start to matter.

Why Markdown was an important design choice

One decision that helped more than I expected was converting job descriptions into Markdown very early in the pipeline.

Raw HTML is noisy. It is awkward to inspect, annoying to diff, and generally a poor format for anything you want to process twice.

By normalizing each position into Markdown, I get a format that is:

  • easy to inspect manually,
  • easy to diff,
  • easy to archive,
  • and much easier to pass into LLM prompts.

That gives me a stable intermediate format between collection and analysis. In practice, it makes the whole pipeline easier to inspect and much less brittle.

LangChain as the analysis layer

The part that matters most is the filtering and scoring stage.

I used LangChain with a local Ollama model to analyze each role. The prompt receives two inputs:

  • the normalized job description,
  • and my CV converted into Markdown.

From there, the model produces a structured JSON response with fields such as:

  • company name,
  • salary if detected,
  • remote suitability,
  • consultancy vs product signal,
  • fit score from 1 to 10,
  • and a short explanation of the score.

This is the point where the project stops being a generic filter and starts becoming a positioning tool.

The question is not only “is this a plausible role?” The more useful question is: “if I take this role seriously, does it move my profile in the right direction?”

For me, that is a better use of an LLM than having it write cover letters full of synthetic enthusiasm.

Scoring against my actual CV

This scoring step matters because it forces the alignment criteria to be explicit.

My CV is not there as background context for generation. It is there as the reference point for ranking.

That means the system can prioritize roles where the overlap is strongest across dimensions like:

  • senior Python backend work,
  • platform and infrastructure ownership,
  • production-grade API design,
  • data and ETL experience,
  • ML productization,
  • and increasing proximity to applied AI engineering.

That last point is the important one.

I am deliberately biasing the search toward roles close to AI engineering, LLM product work, inference systems, AI tooling, developer platforms, or applied automation. A role does not need to be called “AI Engineer” to be strategically useful. Sometimes the title matters less than the trajectory it creates.

That is exactly the kind of judgment I want the system to support.

Why local inference was the right tradeoff

I ran the analysis with a local model through Ollama.

For this kind of workflow, local inference is a good fit:

  • lower marginal cost for repeated scoring,
  • fast iteration on prompts,
  • privacy over personal CV data,
  • and no dependency on a third-party API for every batch run.

The model is not solving an open-ended research problem. It is doing bounded classification and ranking over structured text. For that kind of task, local inference is a reasonable tradeoff.

That is one of the things I like about this project. It is not AI for the sake of it. The model is there because it helps with throughput and improves decision quality in a narrow, practical part of the workflow.

Persistence, deduplication, and traceability

I also wanted the workflow to behave like a real system, not just a script I would throw away after two weekends.

Each analysis is persisted with metadata such as latency, token counts, score, and reasoning. Results are stored in JSONL and SQLite, and a content hash prevents re-analyzing the same position unnecessarily.

So far, the database holds 1,683 analyzed roles with an average score of 6.56/10. If I apply a stricter cut for remote, non-consultancy roles and exclude obvious mismatches such as junior or freelance positions, the current pool drops to 216 roles with an average score of 7.74/10.

That gives me three useful properties:

  • I can audit what the model decided.
  • I can avoid wasting compute on repeated inputs.
  • I can inspect the quality of the pipeline over time.

That matters because once a tool becomes even slightly useful, observability stops being optional. Even in a personal project, I want to be able to understand what happened and why.

The part I am deliberately keeping lightweight

There is a collection layer at the beginning of the workflow, but I do not see that as the interesting part.

The interesting engineering work starts after the positions have been collected: normalization, scoring, ranking, persistence, and decision support.

That is the part that feels reusable, extensible, and professionally relevant.

The next step: tracking applications as a separate service

Right now the project focuses on collection and analysis.

The next obvious step is a separate service, with its own API and dashboard, to track the lifecycle of each position: shortlisted, applied, interview in progress, rejected, stalled, or closed.

The idea is straightforward:

  • this analysis pipeline identifies and scores opportunities,
  • the tracking service becomes the operational system of record,
  • and the two layers communicate so I can query the live state of any position from the analysis side.

I have not wired that integration end to end yet, but architecturally that is clearly where this wants to go.

That split also makes sense from a product point of view. Discovery and scoring are one concern. Application tracking and reporting are another.

Why this project matters for my profile

I built this because it is useful, but also because side projects usually say something about how you think.

This one communicates a few things I want to be clear:

  • I can apply LLMs to practical workflows instead of demo-only use cases.
  • I know how to wrap AI components inside clean software boundaries.
  • I think in terms of systems, feedback loops, and operational visibility.
  • I use automation to improve decision quality, not just to remove clicks.

That is the positioning I care about.

I do not want to come across as someone vaguely “interested in AI.” I would rather be seen as an engineer who can take a messy workflow, find the right abstractions, use LLMs where they actually help, and ship something useful without turning it into theater.

This project is a small example of that.

And, honestly, that is probably the best use of personal tooling. Not just saving time, but making your way of thinking visible in a concrete way.