A code archaeology

How LLMs Began to Code

From next-token prediction to tool-using software agents

IIT Gandhinagar · Agentic Engineering

The thesis

LLMs did not suddenly “become programmers.” A text-prediction engine was specialized, given better interfaces, trained on feedback, and placed inside an execution loop.

01

Predict

Continue text

02

Specialize

Learn code's distribution

03

Instruct

Follow intent

04

Call tools

Emit structured actions

05

Close loop

Act, observe, retry

The original primitive: continue the sequence

Training

context                  target
The quick brown fox   →   jumps
def add(a, b):        →   return

Minimize next-token prediction error across huge text corpora.

Inference

prompt + generated tokens
          ↓
  next-token distribution
          ↓ sample
   one more token ↺

Code is text with unusually strong structure—and executable semantics.

2019 · GPT-2: tasks emerge from continuation

1.5B

parameters

1,024

token context

WebText8M pagescausal LM

Diverse web text contains naturally occurring demonstrations: question → answer, English → French, comment → code.

Key idea: a sufficiently broad continuation model begins to behave like a multitask learner—without a labeled dataset for every task.

But: GPT-2's paper did not claim serious production-quality code generation.

2019 · GPT-2 already found the Tab key

An early bridge

Deep TabNine

A GPT-2-based, all-language code completer put a language model behind editor autocomplete in July 2019.

  • Code before the cursor became the prompt.
  • The product optimized for latency and acceptance.
  • The developer stayed in control: accept, edit, reject.
function slugify(input) {
  // cursor ▌
}

↓ TAB

return input
  .toLowerCase()
  .replace(/\s+/g, '-');

2020 · GPT-3: scale turns prompting into an interface

175B

parameters

2,048

token context

zero-shotone-shotfew-shot

Description: red button saying Stop
Code: <button style=...>Stop</button>

Description: blue box with 3 circles
Code: ...

Description: rainbow buttons
Code: [model continues]

The task is specified inside the context; model weights do not change at use time.

13 July 2020 · “Describe a layout” → JSX

Sharif Shameem's July 2020 X thread showing a GPT-3 JSX layout generator
The two description-to-JSX examples used as in-context demonstrations

PRIMARY-SOURCE SCREENSHOT

Sharif Shameem's demo

  • Natural language → JSX
  • Only two in-context examples
  • A human-built app rendered the output
  • 512-token limit broke some larger tables

Spectacular generation.
Not yet a repository-aware agent.

Original X thread · Two-example follow-up · Correct spelling: Sharif Shameem

Capability discovered before the coding product

HUMAN

Describe

“Three colorful buttons”

MODEL

Complete

GPT-3 continues the pattern

TEXT

Return JSX

Plausible code response

HUMAN

Integrate

Paste · render · debug · retry

GPT-3 could emit code. It could not inspect your repository, run the build, see the failure, or repair it.

The human was the integration layer and the feedback loop.

A parallel track: GitHub × OpenAI

Jun 2020

GPT-3 API preview; GitHub begins experimenting after release.

2020 H2

Question→snippet prototype gives way to inline IDE completion.

29 Jun 2021

Copilot technical preview—Codex under the hood.

7 Jul 2021

Codex paper: GPT-family models fine-tuned on public GitHub code.

10 Aug 2021

Codex API beta: natural-language instructions to code.

Parallel histories: independent GPT-3 demos revealed a capability; GitHub and OpenAI specialized it into a model + editor product. The exact collaboration start date is not public.

Codex: code changes the prior

ArXiv abstract page for Evaluating Large Language Models Trained on Code

up to 12BHumanEvalGitHub code

  • GPT-family models fine-tuned on public GitHub code
  • HumanEval measured functional correctness with unit tests
  • Codex-12B: 28.8% pass@1; tested GPT-3 baseline: 0%
  • A distinct production descendant powered early Copilot

Still a probability model: specialization raises the probability of valid code; it does not install a compiler inside the weights.

One capability, two product worlds

A · Tab-complete world

code before cursor
       
code after cursor
  • milliseconds matter
  • suggestion must fit local intent
  • accept / edit / reject
  • developer stays in the editor

VS

B · Instruct → copy world

“Write a React component…”
            ↓
        code block
            ↓
       copy / paste / run
  • conversation matters
  • longer, task-shaped outputs
  • human transfers state and errors

March 2022 · even one API exposed both worlds

Insert

prefix + suffix → insertion

prompt:  code before cursor
suffix:  code after cursor
output:  missing middle

Completion track: constrain the generated span with both sides.

Edit

instruction + input → edited copy

input:        existing text
instruction:  “fix the bug”
output:       rewritten text

Instruction track: state a desired transformation in natural language.

Tab completion: the cursor is the prompt

GitHub Blog page announcing GitHub Copilot

PRODUCT EVIDENCE

29 June 2021

GitHub described Copilot as suggesting whole lines or entire functions as the developer typed.

active file + nearby code
       + cursor position
              ↓
          ghost text
              ↓
      accept / edit / reject

Why left-to-right completion is not enough

Prefix-only model

def clamp(x, low, high):
    # cursor ▌

assert clamp(12, 0, 10) == 10

The model sees the function prefix. The assertion below may be invisible to its prompt.

Fill in the middle

PREFIX: function + comment
SUFFIX: assertion below
MIDDLE: ?

Generate code constrained by both what comes before and what must still come after.

FIM: rearrange the example, keep the same loss

flowchart TD D["Original file: P + M + S"] --> Q{"FIM transform?"} Q -->|No| A["P · M · S · EOT"] Q -->|PSM| B["PRE P · SUF S · MID M · EOT"] Q -->|SPM| C["SUF S · PRE P · MID M · EOT"] A --> L["Same next-token loss"] B --> L C --> L L --> G["One decoder learns append + insert"]
Original
[ PREFIX ][ MIDDLE ][ SUFFIX ]

PSM
<fim_prefix> PREFIX
<fim_suffix> SUFFIX
<fim_middle> MIDDLE

SPM
<fim_suffix> SUFFIX
<fim_prefix> PREFIX
<fim_middle> MIDDLE

The decoder is still left-to-right. The data transform ensures it has attended to both sides before predicting the hole.

What the suffix teaches the completion

Editor buffer

function total(items) {
  
}

console.log(total([
  { price: 2 },
  { price: 3 }
])); // 5

Prefix-only knows the function name. FIM also sees the call shape, input schema, closing brace, and expected output.

Generated middle

return items.reduce(
  (sum, { price }) => sum + price,
  0
);

The suffix becomes a lightweight specification.

FIM predicts a span. It still does not run the code or verify that the inferred behavior matches the user's real intent.

FIM grew into a code-model lineage

DateModel / workWhat advanced
15 Mar 2022OpenAI InsertProduct API accepted prefix + suffix
12 Apr 2022InCoderZero-shot arbitrary, multi-hole code infilling
28 Jul 2022OpenAI FIM studyPSM/SPM recipe; little loss to normal completion
9 Jan 2023SantaCoder1.1B prototype; joint PSM + SPM
May 2023StarCoder15.5B, 8K context, FIM on 1T training tokens
24 Aug 2023Code LlamaIDE-oriented infilling variants + long context
25 Jan 2024DeepSeek-CoderProject-level data, 16K windows, FIM insertion

Result: autocomplete evolved from “append the next line” into insertion, refactoring, and multi-line next-edit prediction.

Meanwhile: the instruction branch

BASE

GPT-3

Predict likely continuation

SFT

Demonstrations

Learn desired responses

RM

Rankings

Model human preference

RLHF

Optimize

Follow intent more reliably

InstructGPT · 2022

Making the model bigger did not automatically make it better at following user intent. Post-training shaped the assistant interface.

What it did not supply

No repository state, no shell, no permissions, no autonomous action loop.

Chat coding: the human becomes the harness

sequenceDiagram actor Human participant Chat as Chat model participant Repo as Editor / repo participant Test as Build / tests Human->>Chat: “Implement feature X” Chat-->>Human: code block Human->>Repo: copy / paste Human->>Test: run Test-->>Human: error output Human->>Chat: paste error Chat-->>Human: revised code

Conversation added iteration. The human still moved every action and observation.

13 June 2023 · actions become grammatical

OpenAI function calling

Fine-tuned models learned to:

  1. decide whether a function is needed;

  2. choose the function;

  3. emit structured JSON arguments.

Proposal, not execution: application code still validates, authorizes, runs, and returns the result.

{
  "name": "run_tests",
  "description": "Run a test target",
  "parameters": {
    "type": "object",
    "properties": {
      "target": { "type": "string" }
    },
    "required": ["target"]
  }
}

A tool call is one turn in a protocol

01

Describe

Host sends schemas

02

Propose

Model emits call + args

03

Authorize

Host validates policy

04

Execute

Tool returns result

05

Continue

Result becomes next message

messages + tool schemas → tool_call → execute → tool_result → model continues

The security boundary lives in the host: schema validation · permissions · sandbox · timeouts · logging · stop conditions

25 November 2024 · MCP standardizes the other side

Anthropic announcement page Introducing the Model Context Protocol

Model Context Protocol

  • Open standard announced by Anthropic
  • Host–client–server architecture over JSON-RPC 2.0
  • Servers expose tools, resources, prompts
  • Reusable integrations across hosts and models

MCP does not train the model. It standardizes discovery and transport between the host and external capabilities.

OpenAI tool spec ≠ Anthropic MCP spec

Model-facing contract

Function / tool calling

Schema in request; model emits tool name + arguments.

Integration-facing protocol

MCP

Client discovers servers and transports calls, results, and resources.

LLM · native tool-call format

⇅ name + JSON / tool result

Agent host · state · policy · approvals

⇅ bridge

MCP client

⇅ JSON-RPC · tools/list · tools/call

MCP server

⇅ integration

Git · files · databases · APIs

The host bridges the two layers. Neither JSON Schema nor MCP executes anything by itself.

Post-training: four different lessons

StageSignalWhat the model learns
Instruction SFTExpert demonstrationsAnswer this kind of request
Tool-call SFTCalls + valid argumentsWhen / which tool / what JSON
RLHFHuman preference rankingsBe helpful, safe, cooperative
RLVR / execution RLTests, compilers, environment outcomesPrefer actions that actually work
Coding is unusually suitable for verification: programs can be parsed, compiled, run, and tested.

Did RLHF / RLVR “make the model agentic”?

Not by itself.

agentic behavior = model policy + tools + stateful harness + environment feedback + permissions + stopping rules

RLHF

Improves instruction-following and interaction quality.

Tool training

Improves structured action selection and arguments.

RLVR

Rewards trajectories and outputs that survive verification.

The harness supplies the loop in which these behaviors matter.

Verifiable rewards: from plausible to executable

Task + repository snapshot

Agent rollout · read · edit · run

⇅ observations · diffs

Sandboxed repository

↓ patch + hidden tests

Verifier → scalar reward

↓ optimize

Update policy θ ↺ next rollout

Cheap outcome signals

Parse · typecheck · lint · unit tests · integration tests

Proxy, not truth: passing tests can still miss security, maintainability, performance, or the actual requirement.

At training time, reward updates weights. At inference time, test output becomes context for the next attempt.

The agentic loop: chat and tool calls interleave

sequenceDiagram actor U as User participant H as Agent harness participant M as LLM participant E as Repo + tools U->>H: Fix the failing parser test H->>M: task + history + tool schemas loop Until done, blocked, or budget exhausted M-->>H: tool_call(name, arguments) H->>H: validate policy / approval H->>E: execute tool E-->>H: observation: file / stdout / diff / error H->>M: append call + tool result end M-->>H: final response, no tool call H-->>U: summary + changed files + test evidence

One user turn can contain many model/tool subturns. The model proposes; the harness authorizes and executes; each observation becomes the next message.

The arc in one line

completion → infilling → instruction → tool calls → verified action loops

Model

patterns · instructions · action policy

Harness

state · tools · permissions · loop

Evidence

tests · diffs · logs · human judgment

The biggest leap was closing the loop between generation and evidence.