Add a vLLM provider
- Status: Done
- Kind: Feature
- Authors: jp
- Date: 2026-09-16
- Label: domain=llm
- Label: package=jp_config
- Label: package=jp_llm
- Label: type=feature
vLLM serves GET /v1/models and POST /v1/chat/completions behind a Bearer token, speaking the same Chat Completions dialect that jp_llm::provider::openai_compat already parses for llama.cpp. A vLLM provider is therefore mostly config plumbing plus a thin provider module over the shared dialect code.
Config
ProviderId::Vllminjp_config::model::id, withas_str() == "vllm".providers/llm/vllm.rsholdingVllmConfig:api_key_envdefaulting toVLLM_API_KEY, andbase_urldefaulting tohttp://127.0.0.1:8000. The four trait impls (AssignKeyValue,PartialConfigDelta,FillDefaults,ToPartial) followdeepseek.rs.- A
vllmfield onLlmProviderConfig, wired into each of the four impls inproviders/llm.rs. - The
jp_configsnapshots for config fields, schema shape, and partial defaults all move; review them withcargo insta.
Provider
- Hoist
to_system_messages,convert_events,convert_tools, andconvert_tool_choiceout ofllamacpp.rsintoopenai_compat.rsaspub(crate), and have llamacpp call them there. Behavior-preserving. provider/vllm.rswithVllm { client, base_url }.TryFrom<&VllmConfig>reads the key from the environment and sets the Bearer header, ascerebras.rsdoes.models()mapsGET /v1/modelsentries toModelDetails, takingcontext_windowfrom the reportedmax_model_lenand keeping the full id (e.g.Qwen/Qwen3-8B) as the name.model_details()returnsModelDetails::empty()for an unknown name.create_request()builds the chat body: model, messages, stream, temperature, top_p, max_tokens, tools, tool_choice,response_formatfor a structured schema, andchat_template_kwargs.enable_thinkingfrom the reasoning setting. Noreasoning_formatfield — that one is llama.cpp-specific.chat_completion_stream()posts it and parses the SSE stream withparse_chunk().mod vllm, theget_provider()andbuild_request_value()arms inprovider.rs, and theVllmarms intest.rsforbase_urlandapi_key_env.vllm_tests.rscoveringcreate_request()for a plain message, a tool call round trip, a structured schema, and reasoning off, each against a static expected JSON body.
Docs
Name vLLM in the provider sentence in docs/features/tools.md.
Comments
- From: jp
- Date: 2026-09-16T02:01:11Z
Filed after the fact: the config, provider, and docs work described above is implemented and staged. Deviations from the original plan worth recording:
- The plan also called for adding vLLM to a provider list in
docs/configuration.md. That file has no provider list, so there is nothing to add there. - The plan's dotfiles step (the
nebiusalias and the[providers.llm.vllm]table inagentic-shepherd/dotfiles/jp-user-config/user-config.toml) lives in another repository and is out of scope here.