Add local-model variant of the opportunities agent - #8
Open
makegov-mark[bot] wants to merge 2 commits into
Open
Conversation
`local_agent.py` is the mirror of `agent.py` swapped onto any OpenAI-compatible endpoint (Ollama, LM Studio, vLLM, llama.cpp). Same tool catalog and same loop shape so the two files diff cleanly — the diff itself is the lesson on where the Anthropic and OpenAI tool-use protocols differ. Carries a separate, hardened `LOCAL_SYSTEM_PROMPT` because soft guidance like "two empty searches is a signal to stop" that Sonnet self-regulates on lets a ~30B local model burn every available turn keyword-grinding. Numbered hard rules, per-phase call caps, and a tighter MAX_TURNS=6 turn a failed local run into a working demo. Also tightens the SAM.gov link surfaced in the brief — both the Anthropic and local variants now ask Tango for the `sam_url` field via the `shape=` parameter rather than constructing it client-side. Tango computes it using the latest notice id with hyphens stripped, which is what SAM.gov actually accepts; the original opportunity_id (hyphenated) silently 404s on SAM. As a side effect, the corrected `shape` field names (`naics_code`/`psc_code`, not `naics`/`psc`) make six fields the original `_trim_opportunity` was aspirationally requesting actually show up in the tool result for the first time.
`{{question}}` substituted the literal string into the recipe, so apostrophes
in questions like "that's likely the incumbent I'd be competing against"
landed in /bin/sh as an unmatched single quote and the recipe died with a
syntax error before python ever ran. `{{ quote(question) }}` wraps the value
with single quotes and escapes embedded singles as `'\''`, so the user can
pass any question they want.
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.
Summary
examples/opportunities-agent/local_agent.py— the mirror ofagent.pyswapped onto any OpenAI-compatible endpoint (Ollama, LM Studio, vLLM, llama.cpp). Same tool catalog, same loop shape; the two files diff cleanly so the diff itself is the lesson on where the Anthropic and OpenAI tool-use protocols differ.LOCAL_SYSTEM_PROMPT+ tighterMAX_TURNS=6— soft guidance like "two empty searches is a signal to stop" that Sonnet self-regulates on lets a ~30B local model burn every available turn keyword-grinding. Numbered hard rules and per-phase call caps turn a failed local run into a working demo.sam_urlnow comes from Tango (in bothagent.pyandlocal_agent.py) — the brief includes a clickable SAM.gov link. Tango computes it using the latest notice id with hyphens stripped, which is what SAM.gov actually accepts; the original opportunity_id (hyphenated) silently 404s on SAM. Done by requestingsam_urlvia theshape=parameter rather than constructing the URL client-side.shape=string (naics_code/psc_code, notnaics/psc), six fields the original_trim_opportunitywas aspirationally requesting actually show up in the tool result for the first time.just local-agent,openai>=1.50in theexamplesdependency group, andLOCAL_MODEL/LOCAL_BASE_URL/LOCAL_API_KEYdocumented in.env.example.Test plan
just agent(default question) — still works against Anthropic, sam_url now appears in the briefjust local-agentagainst LM Studio (google/gemma-4-26b-a4b-qat) — clean 3-call run, brief includes correct SAM.gov link (hyphens stripped, latest notice id)just local-agent "<harder SDVOSB question>"against remote vLLM endpoint — completes under MAX_TURNS, honest "no incumbent found"curl -I https://sam.gov/opp/<id>/view)Caveats