Repository navigation
v1.13.5
Changes
Prompture could talk to almost any model, but an agent built on it still had to bring its own way to search, read a page or watch a video, and nobody could easily tell which of those actually worked on a given machine. This PR adds that capability layer: web search, page and URL readers, transcription, an MCP hub, wrapped CLI tools, domain packs and a research agent, all built on a shared foundation of ordered backend chains that fail over instead of failing. prompture doctor reports what works, which backend is active and the exact fix for anything that doesn't. It also fixes GPT-6 models (including gpt-6-astra) being rejected, and Ollama ignoring max_tokens.
Highlights
- Web search, page fetching and URL readers work with no API keys at all; adding keys raises quality and limits, and every result says which backend served it and whether it fell back
read_urlunderstands YouTube, GitHub, Hacker News, arXiv, Wikipedia, RSS/Atom feeds and podcasts, and falls back to a plain page fetch for anything else- Repeat searches and static pages come back instantly from a local cache, even in a new process; weather, prices and news expire in minutes, papers and transcripts in days, and cached results say how old they are
prompture transcribeandsummarize_mediaturn a video, podcast or audio file into a timestamped transcript and a summary with key points; audio is never sent to a second provider without opting inprompture research "question"produces a cited report from pages it actually opened, within fetch, token, cost and time budgets- Agents mount tools by name:
tools=["web:all", "mcp:exa", "pack:finance", "cli:gh"] prompture mcp add --preset exaregisters MCP servers once and reuses them by name; secrets are stored only as${ENV}referencesprompture doctorshows every provider, tool, media piece, MCP server and binary with its status, active backend and fix;prompture setup/configurestore keys in an owner-only file with profilesprompture skill installgives coding agents a skill describing all of this, andprompture check-update/watchreport new releases- GPT-6 models (
gpt-6-astra,gpt-6-luna,gpt-6.1-sol) no longer fail with "Unsupported parameter: max_tokens", and Ollama now honorsmax_tokens, temperature and the other sampling controls
Technical changes
Capability foundation (prompture/capabilities/)
BackendChaintriesBackends in order, skips unavailable ones and classifies failures throughclassify_error: transient errors retry once, auth/quota/rate-limit/challenge errors move to the next backend, and fatal errors re-raise with the attempts attached asexc.attempts. Results areChainResults withroute = {served_by, fallback, attempts}- An env override (e.g.
PROMPTURE_SEARCH_PROVIDERS) moves named backends to the front and keeps the rest in place after them; unknown names are ignored so a stale value can't hide working backends.only=restricts the chain classify_backend_errorpinsUnsafeURLError(fatal),ChallengePageErrorandResponseTooLargeError(failover) to fixed actions, soreset_error_rules()can't turn an unsafe URL into a failoverprobe_commandruns a side-effect-free command with a UTF-8 child env and stripped interpreter variables and classifiesok | missing | broken | timeout | error; exit 126/127, exec failures and "No Python at" style output count asbroken.cached_probeshares results for 60 sHealthStatusand a capability registry (register_capability,check_capabilities) that doctor walks; a crashing check becomes anerrorrow instead of breaking the reportnormalize_public_http_urlallows only publichttp(s): it blocks private, loopback, link-local, metadata, CGNAT, multicast and reserved ranges, IPv4-mapped / 6to4 / Teredo / NAT64 wrappers, decimal/octal/hex IPv4 spellings and internal hostnames, and checks every resolved address.PROMPTURE_WEB_ALLOW_PRIVATEis the escape hatchGuardedHTTPAdapterchecks the address each socket actually connected to before any request bytes are sent, closing the DNS-rebinding gap between validating a hostname and connecting to it.safe_getmounts it on its own session and on anyrequests.Sessionpassed in; connections to a configured proxy are exemptsafe_getfollows redirects manually and re-validates each hop, streams the body with a byte cap, detects challenge pages and raises typedHTTPStatusErrors that carry status and headers. Proxies come fromPROMPTURE_<BACKEND>_PROXYorPROMPTURE_PROXYis_challenge_pagescores combined Cloudflare / captcha markers in the first 4 KB, requiring more evidence on 2xx responsesscrub_url_credentials/scrub_secretsremove URL userinfo, bareuser:pass@host, secret-looking query/fragment parameters, known API key shapes and bearer tokens. They're applied toDriverHTTPErrormessages, every capability error and health row, and a newSecretScrubbingFilterinstalled byconfigure_logging, which also scrubs rendered tracebacks (exc_text) and stack infoprompture/tools/named.pyresolves"namespace:name"tool specs;Agent,AsyncAgentandDeepAgentaccept them next to callables andToolDefinitions
Web tools (prompture/tools/web/)
- Search backends
tavily,exa,serper,brave,jina,searxngand keylessexa_mcp(a minimal JSON-RPC client over streamable HTTP, nomcpdependency) behindweb_search/asearch, with domain filters, recency, URL dedupe and aSearchResponsecarrying the route web_fetchchainsjina_readeranddirect(safe_get+ stdlib HTML to Markdown,trafilaturawhen installed), validates the URL before any backend sees it, pages long content withstart=and caches for 10 minutesread_urlroutes to readers (YouTube transcript API, thenyt-dlpsubtitles, then transcription; GitHub REST, thengh; HN Firebase; arXiv API; Wikipedia REST; podcast enclosures; feeds), with per-reader step overrides viaPROMPTURE_READER_<NAME>_BACKENDSsearch_platformfor YouTube, GitHub (repositories, issues, code), Hacker News and arXiv;WebToolkitand theweb:namespace build agent tools that return strings and never raiseWebSearchToolkeeps its signature; with nothing configured it now falls back to keyless search instead of raising- New
prompture/tools/web/cache.py: search, fetch,read_urland platform search share a cache built on the existingMemoryCacheBackend/SQLiteCacheBackend(default SQLite at~/.prompture/cache/web_cache.db, 5,000 entries;PROMPTURE_WEB_CACHE=memory|off,PROMPTURE_WEB_CACHE_PATH). Lifetimes come fromttl_for: volatile queries (weather, prices, scores, news,recency_days <= 1) and fast-moving hosts 10 min, feeds 15 min, platform search 30 min, ordinary pages 1 h, other searches 6 h, Wikipedia and podcasts 1 day, papers, PDFs, DOIs, commit-pinned GitHub files and YouTube transcripts 7 days read_urlcaches the full reader result and pages from it, so walking a long transcript never refetches. Errors and empty results are never stored, values over 2 MB stay out of the disk cache, and hits carryroute["cached"]/cache_age_splus a "cached N min ago" footer. Every entry point takesuse_cache=andcache_ttl=;clear_web_cache(),cache_info()(read-only, never creates the database) and aweb_cachedoctor row round it out
Media understanding (prompture/media/understand/)
transcribeaccepts a URL or file, downloads direct audio throughsafe_getand video/podcast pages throughyt-dlp, then downmixes and chunks long media withffmpegand stitches the timestamps. It enforces caps on source size, chunk count and upload bytes, and cleans up temp files infinallyautopicks the first configured STT provider (Groq, OpenAI, ElevenLabs; reorder withPROMPTURE_STT_PROVIDERS); a second provider is used only withallow_provider_fallback=True- New
GroqSTTDriver, STT usage recorded throughrecord_media_usage,summarize_mediamap-reduce summaries with timestamped key points,transcribe_media/summarize_mediaagent tools, andprompture transcribe
Doctor and updates
prompture.doctor.check_all()returns aDoctorReportwith a versionedprompture.doctor/1JSON schema. The providers section checks key presence, base URLs, SDK importability and driver import offline, and--livelists models only, never generating anything paid. Unconfigured providers collapse into one rowprompture doctor,check-update(one PyPI call cached for 24 h, with changelog highlights) andwatch(exit 1 when something is broken, 2 for an update only with--fail-on-update)- The companion info payload gains a
healthsummary, cached and never blocking
Setup and credentials
CredentialStorewrites~/.prompture/credentials.yamlonly on first write, owner-only (0600, or a user-only ACL viaicaclson Windows), atomically, refusing symlinks and junctions, with a 1 MB read cap and profilesSettingsreads the store below env vars and.env;get_config_valuegives the same precedence to proxies and backend overridesdetect_environmenttells local machines from servers (container, CI, SSH, headless);prompture setup,configureandresetall support--dry-run, validate keys live and never echo them
MCP hub (prompture/mcp/hub.py)
- Named servers in
~/.prompture/mcp.jsonplus a project.prompture/mcp.jsonthat wins by name. Literal secrets are refused in favor of${ENV}references resolved at connect time resolve_mcp_toolsbacksmcp:<name>with pooled sessions on a background loop so sync agents can call them, per-server timeouts,<server>__<tool>prefixing and usage-ledger entries per callhttp_sessionfor streamable HTTP, presets (exa,deepwiki,github,fetch,time,git,memory,filesystem,sequential-thinking), opt-in import from editor configs, andprompture mcp add|list|remove|enable|disable|test|importbuild_mcp_serverworks on bothmcp1.x (FastMCP) and 2.x (MCPServer)
CLI tools and packs
CLIToolturns a declared argument schema into an argv list with no shell. Only declared subcommands are allowed, flag injection is blocked, every run has a timeout and output cap, injected env values are never logged, and shells and Windows batch launchers are refused- Built-in
gh(read-only;gh apiforced to GET) andyt-dlptools, plus user definitions from.prompture/tools.yaml - Tools defined in a project's
.prompture/tools.*are untrusted: health checks andcli:allonly locate their executable and never runversion_args/live_check_args, so runningprompture doctorin a cloned repository can't execute its code. Shipped tools and~/.prompturedefinitions are still probed, and a config file can't mark itself trusted finance,news,devandplacespacks built on Tukuy plugins, the web readers and the PyPI/npm JSON APIs; tools missing a key are left out and listed in the pack's health row
Research agent (prompture/research/)
ResearchAgentplans sub-questions, fans out searches, platform queries and packs in parallel, then ranks and dedupes URLs with per-domain caps and reads the top pages, transcribing media when useful- Under a token or cost budget, pack LLM calls take turns: the budget check and usage recording happen under one lock, so parallel packs can't all start against the same remaining budget. The default model reads
PROMPTURE_RESEARCH_MODEL/PROMPTURE_DEFAULT_MODELfrom the credential store too, so the model chosen inprompture setupis used - Synthesis cites only opened sources and strips any other
[n]. Budgets are enforced across threads; when a limit hits, the agent answers from what it already read, or falls back to cited excerpts prompture research,research_tool()andResearchEventprogress events
Agent skill and docs
- Bundled
SKILL.mdwith standing rules and a routing table to per-capability references. It states which capabilities are keyless (web search and reading) and that failover is per capability, with transcription never moving audio to a second provider without consent;prompture skill install|uninstall|showwrites only to an explicit target and removes only directories it created llms.txt,docs/agent-install.mdanddocs/agent-update.md
Fixes
_default_tokens_parampicksmax_completion_tokensby model generation (gpt-Nwith N ≥ 5, plus the o-series) for bothopenaiandazure. GPT-6 models previously gotmax_tokensand a 400, and Azure sentmax_tokenseven forgpt-5.5- Ollama drivers move temperature,
top_p,top_k,num_ctx, seed,repeat_penalty,min_pandnum_predict(frommax_tokens) into theoptionsobject Ollama reads, and forwardthink - The CLI replaces characters the console can't encode instead of crashing on piped Windows output, and loads capability commands from their own modules
- The MCP tool-name digest uses
sha1(..., usedforsecurity=False), since it only keeps names unique - The companion router stores a reusable non-streaming answer before writing the body to the client. It used to store it afterwards, so a near-identical request sent the moment the first one finished could miss the cache and reach the vendor again
Packaging and config
- New
web(feedparser, youtube-transcript-api, trafilatura) andmedia(yt-dlp) extras, both included inall; skill files shipped as package data - New
EXA_API_KEYsetting;GITHUB_TOKENnow also serves the GitHub reader .env.copydocuments every new variable. The README gains an intro section right after the quick start, a Capabilities group in Key Features and a full Capabilities guide; top-level exports include the new APIs, with doctor and research loaded lazily soimport prompturestays as fast as before