How a Staff Engineer Spots AI Code in Take-Home Exercises

Detecting AI-generated code in take-home interviews comes down to three assets most hiring teams already have: a baseline of what the candidate wrote under direct observation, a deadline that forces a decision, and a follow-up conversation where the candidate has to defend the code line by line. Teams that catch AI assistance use all three. Teams that lean on a single percentage from a detector usually do not.

Dana Whitfield runs platform engineering at a 400-person payments company in Austin. Last spring she opened a submission that had passed all 22 unit tests on the first push: four files, 640 lines, an AI probability of 0.87 on one file and between 0.04 and 0.09 on the rest. "The tests were green and the code was gorgeous and I could not have explained a single function in it," Whitfield said. The candidate had generated the core scheduler with a model and hand-written the parser and the test suite. Whitfield's verdict after a 30-minute call was to hire.

Where AI-generated code in take-home interviews actually shows up

The all-or-nothing case, where a candidate pastes the prompt and returns whatever Claude 3.5 Sonnet or GPT-4o produced, is now the minority. The common artifact is a hybrid. A candidate generates the hard part with a model, then edits the parts they understand well enough to talk about, and the seam between the two shows up in places that have nothing to do with correctness.

Whitfield describes a consistent geography. Whole-submission generation tends to produce uniform file lengths, a README that restates the prompt in the same register, and a test suite that covers every branch with suspicious symmetry. Partial generation produces a discontinuity: one module with full type annotations and a docstring on every function, next to a module with a single comment reading # this is broken lol.

"We stopped asking whether the model wrote it," Whitfield said. "The useful question is whether the candidate can maintain it, and that question has an answer we can actually verify in half an hour."

The distinction matters for policy as much as for evaluation. A team that treats any AI involvement as disqualifying will reject people who used a completion tool the way earlier generations used Stack Overflow, and it will burn a lot of interview hours doing it. A team that treats AI involvement as a signal to probe more deeply tends to make better hires and fewer accusations.

Reading a submission for style mismatch

The cheapest detector is two files from the same candidate, side by side, written a few days apart. Below are excerpts from a real screening exercise: a log parser, first drafted in a supervised 90-minute session, then extended at home with a second entry point.

# File 1, written in the supervised session
def parse_line(line):
    # 2023-04-11 09:12:44,INFO,checkout,user=8821 status=200 47ms
    parts = line.split(",")
    if len(parts) < 3:
        return None
    ts, level, svc = parts[0], parts[1], parts[2]
    rest = ",".join(parts[3:])
    return ts, level, svc, rest
# File 2, same candidate, same prompt, uploaded three days later
from typing import Optional, Tuple
import logging

logger = logging.getLogger(__name__)

def parse_log_line(line: str) -> Optional[Tuple[str, str, str, dict]]:
    """Parse a single log line into its component fields.

    Args:
        line: A raw log line string.

    Returns:
        A tuple of (timestamp, level, service, fields), or None on failure.
    """
    if not line or not isinstance(line, str):
        raise ValueError("line must be a non-empty string")
    ...

The second file has tells that a reviewer can name out loud. The docstring promises a dict and the annotation promises a tuple. The human version returns None on a malformed line; the generated version raises. Neither behavior is wrong, but they cannot both come from the same mental model of the caller. The first file carries a real log line as a comment, dated and specific, the kind of thing a person pastes while debugging.

None of this proves authorship. A candidate who learned Python from a tutorial that teaches Google-style docstrings will produce the second style all on their own. What the comparison buys is a prior, and a short list of questions to ask on the call.

What an AI code detector adds and what it cannot say

Text detectors built for prose rely on perplexity and burstiness. Prose written by a model tends to use more predictable tokens and to have more uniform sentence complexity than prose written by a person under deadline. Source code defeats both measurements for structural reasons. A for loop is predictable no matter who typed it. Line lengths cluster. Burstiness is close to zero in a well-formatted file because the formatter already removed the variation.

Code-specific detectors work differently. They score token-level predictability against a language-aware model, then fold in formatting and structural features: annotation density, docstring coverage, import hygiene, exception handling breadth, and the distance between what a docstring claims and what the function does. A tool like the AI code detector from Codequiry reports per-file scores alongside written indicators rather than a single opaque number, which matters when the output will be read aloud to a hiring committee or an academic integrity panel.

Codequiry AI code detection report with average AI score, highest file score and a risk distribution
AI code detection: probability scores per file, flagging submissions likely written by ChatGPT, Copilot, Claude or Gemini.
Codequiry per-file AI analysis showing AI versus human probability for each file with written indicators
Drilling into one submission: per-file AI and human probabilities, each with the stylistic indicators behind the score.

The published evidence is thinner than vendors imply. The SIGCSE 2024 study on detecting ChatGPT-generated submissions in a CS1 course reported accuracy above 90% using a combination of stylometric and structural features, but the corpus came from a single course at a single institution and the model was trained and tested on the same assignment family. Code watermarking research, including the 2024 ACL paper on watermarks for generated code, is promising and unavailable in any production model today. In a pilot of 80 past take-home submissions, half rewritten by a model and half left alone, one engineering team found that their detector's error rate varied by a factor of four across languages, with the worst performance on TypeScript files that leaned on a framework's scaffolding.

Codequiry supported programming languages page listing 65 approved languages and custom parser submission
65 supported languages, plus custom parsers for anything unusual a course or codebase throws at the engine.

The walkthrough call does more work than any score

Every practitioner interviewed for this piece described roughly the same protocol, arrived at independently. Twenty-five to thirty minutes. Screen shared, code open. Three questions.

The first is a why question aimed at the highest-scoring block: why this data structure, why this layer, why not the obvious alternative. The second is a destructive request: delete this validation branch and tell me what breaks. The third is an adversarial input: what happens if the message field contains a comma.

A candidate who wrote the code answers all three with varying speed and roughly the same confidence. A candidate who prompted for it tends to answer the first question well, because the model's reasoning is legible, and then stalls on the second, because deleting a branch requires knowing why it exists. "The comma question gets them every time," said Marcus Oyelaran, an engineering manager at a logistics company in Rotterdam who has run this screen for two years. "If they wrote the parser, they know. If they didn't, they say the tests cover it."

The candidates the screen gets wrong

Bootcamp graduates are the largest false-positive group, and the reason is structural. Several popular curricula teach the same scaffold: full type hints, a module-level logger, a docstring template, defensive validation on every public function. A hiring panel that treats that style as an AI signature is penalizing a candidate for having taken a course.

Candidates writing in a second or third language generate a second cluster. Formulaic comments, uniform function lengths, and heavy docstring coverage are all consistent with both a model and with someone translating their intent from Bengali or Polish into English comments.

Then there is the ambiguous middle. A candidate with GitHub Copilot enabled in their editor by habit accepts suggestions without noticing, and the resulting file is a genuine blend of two authors. At one company, an intake form still carries a field labeled "AI suspicion (1-5)" with no rubric attached to it, and two reviewers scored the same candidate a 2 and a 5 in the same week. The panel resolved it by defaulting to the walkthrough call, which is the correct instinct but a poor substitute for a written rubric.

Consent, disclosure, and the policy nobody wrote

Submitting a candidate's code to a third-party detector is processing personal data about an identifiable person, and in most jurisdictions it requires disclosing that in the assessment instructions. Very few hiring teams have written that sentence. The one-line version is not complicated: submissions may be analyzed for originality and AI assistance, and results are used in the hiring decision.

Two regulations are shaping the disclosure norm. New York City Local Law 144, in effect since July 2023, requires a bias audit for automated employment decision tools, and while a code originality screen probably falls outside that definition, the disclosure habit it created has spread. The EU AI Act, in force since August 2024 with obligations phasing in through 2027, puts employment-adjacent AI systems in a higher-risk category that carries documentation and transparency duties. None of this settles whether a 0.87 AI score is grounds for rejection. It does settle that the candidate should know the scan happened.

Choosing a tool for a pipeline that is not a classroom

Most of the tooling in this space was built for coursework. MOSS has been free since 1994, runs on winnowing fingerprints, and communicates by email in an ASCII interface that has not changed in two decades. JPlag, maintained at the Karlsruhe Institute of Technology since 1996, does token-based comparison with a real GUI. Dolos, the TypeScript rewrite, produces good visualizations. All three compare a submission against its peers. None of them detect AI-generated code, and none expose an API a recruiting pipeline can call.

For hiring, the peer comparison is nearly worthless and the web comparison is valuable. A take-home submission should be checked against GitHub, public gists, Stack Overflow answers, tutorial repositories, and the candidate's own published work, because copying a solution from a popular repository is far more common than generating one. A code plagiarism checker that can trace a block of code to a specific Stack Overflow question with line and token counts gives a reviewer something to put in front of a candidate. Codequiry does both jobs in one pass: token, AST, and fingerprint-based similarity against peer and web corpora, plus AI detection across 65 languages, with a REST API and webhooks for teams that want the check to run automatically when a submission lands.

Codequiry web results tracing copied code to GitHub repositories and other web sources with per-domain scores
Web results: every domain a submission matched, scored per source, from GitHub repos to tutorial sites.

Teams that want to detect code plagiarism in a hiring loop should expect to run the scan before the walkthrough call, not after. A score that arrives three days after the offer letter is a data point with no decision attached to it.

The screen does not replace judgment, and no serious practitioner treats it as if it would. What it does is turn a vague unease about a suspiciously polished submission into three specific questions and a thirty-minute conversation. That is a better hiring process than the one most teams had in 2019, when the same submission would have gone straight to the panel unchecked. Teams ready to add the check to their pipeline can run a code originality check against a sample submission before committing to anything.