0.10.0: write a listing with an agent - #42
Merged
Merged
Conversation
An employer with a brief and no time can now have a model expand it into the post form. Set OPENAI_API_KEY or ANTHROPIC_API_KEY and the box appears on /post; set neither and it does not. It fills the form in and stops. Nothing is written, nothing is published, and the person who asked reads and edits every field before a listing exists. That is the same seam an employer's agent goes through when it posts over the API and lands a draft, which is the board's whole thesis rather than a feature bolted onto it. A model writing straight into the database is the one shape this board has said it will not ship. It will not invent compensation. If the brief says nothing about pay, every salary field comes back empty: an employer may not notice an invented range, and a candidate who applies because of a number nobody agreed to has been misled by this board. "Unpaid" has to be stated in the brief rather than inferred from silence, and it arrives as the checkbox 0.9.0 added. Anything the model returns is checked against the same lists the form's own selects are built from, and an unrecognised value is dropped rather than bent into the nearest legal one. The second looks like the employer chose it. Two providers, because this is MIT software other people self-host and a board that only works if you bank with one vendor is not self-hostable. Written against both REST APIs directly: one dependency per provider to fill in a form is a poor trade for a package that reads a .docx by unzipping it by hand. Signed in, and ten an hour per account, recorded before the model is called rather than after. A form that calls a model is a proxy to somebody's paid account, and a request that failed still cost the board something. The provider's own error text never reaches the page: it is written for whoever holds the key and can carry account details. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xXMzJf85q87oeG3VEKHdJ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An employer with a brief and no time can now have a model expand it into the post form. Set
OPENAI_API_KEYorANTHROPIC_API_KEYand the box appears on/post; set neither and it does not.It fills the form and stops
Nothing is written, nothing is published, and the person who asked reads and edits every field before a listing exists. That is the same seam an employer's agent goes through when it posts over the API and lands a draft, which is the board's thesis rather than a feature bolted onto it. A model writing straight into the database is the one shape this board has said it will not ship.
It will not invent compensation
If the brief says nothing about pay, every salary field comes back empty. An employer may not notice an invented range, and a candidate who applies because of a number nobody agreed to has been misled by this board. "Unpaid" has to be stated in the brief rather than inferred from silence, and it arrives as the checkbox #41 added.
Anything the model returns is checked against the same lists the form's own selects are built from, and an unrecognised value is dropped rather than bent into the nearest legal one. Bending it would put a choice on the page the employer never made.
Two providers
This is MIT software other people self-host, and a board that only works if you bank with one vendor is not self-hostable. Whichever key is set wins (Anthropic first if both, so the same brief does not produce different listings run to run). Written against both REST APIs directly: one dependency per provider to fill in a form is a poor trade for a package that reads a
.docxby unzipping it by hand.WRITER_MODELoverrides the per-provider default (gpt-5.2/claude-opus-5). I pickedgpt-5.2over a codex variant because this task is prose, not code;WRITER_MODEL=gpt-5.2-codexflips it.Not a public text generator
Signed in, and ten drafts an hour per account, recorded before the model is called rather than after: a request that failed still cost the board something and still came from somebody. The provider's own error text never reaches the page, since it is written for whoever holds the key and can carry account details.
Testing
185 pass. Twelve new, all without a key or a network because the provider call takes its
fetchas an argument: the request shape each API actually takes (includingmax_completion_tokens, which the current OpenAI models require in place ofmax_tokens), that a refusal arrives as a 200 so the status is not evidence of an answer, that an account identifier in a provider error never reaches the page, that a too-short brief never reaches the model at all, and the parsing rules above.Also run for real against a live key. From "Unpaid research internship, remote, 10 hours a week..." it returned a complete listing with
employmentType: internship,workplace: remote,seniority: intern, no salary range, and the unpaid box ticked.🤖 Generated with Claude Code