OpenHands / OpenHands/software-agent-sdk
feat(profiles): server-side prompt-file composition — `system_prompt_filename` / `system_prompt_kwargs` on `OpenHandsAgentProfile` and `OpenHandsAgentSettings`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 539
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 137
Description
Problem
Measured at v1.44.1 and re-verified at v1.46.0: Agent supports system_prompt_filename (default "system_prompt.j2") + system_prompt_kwargs with the inline↔filename exclusivity validator, rendered through the Jinja escape hatch (agent/base.py:207-262, render at :346-373 at v1.46.0). But every server-side/profile path to an agent drops this channel:
StartConversationRequest.agentis client-composed — the server only appends suffix/tools/plugins; shipping a fullAgentobject from every client is the only way to get a custom prompt FILE today.OpenHandsAgentSettings.create_agent()(sdk/settings/model.py:1365-1401) passesllm/tools/include_default_tools/agent_context/condenseronly — the file contains nosystem_prompt*occurrence at all.OpenHandsAgentProfile(sdk/profiles/agent_profile.py:122-187) carriessystem_message_suffixonly — suffix, not a prompt template file.
Net effect: a deployment that keeps LLM profiles + agent profiles server-side (never shipping provider config to clients) cannot give conversations a custom system-prompt template + kwargs without falling back to client-side agent assembly — which defeats the purpose of profiles.
Ask
Additive fields on OpenHandsAgentProfile and OpenHandsAgentSettings:
system_prompt_filename: str = "system_prompt.j2"
system_prompt_kwargs: dict[str, object] = {}
# optionally: prompt_dir: Path | None = None
forwarded by create_agent() / resolve_agent_profile() into the composed Agent, honoring the existing inline↔filename exclusivity. Profiles then stay server-side, secret-free, and prompt-capable.
Precedent
- #3213 (open): server-side
ConversationSettings.create_request()injectsagent.system_prompt_kwargsviamodel_copy— same direction of composition. - #4029 (closed, completed): added
agent_launch_additionsoverrides on theagent_profile_idpath — the path this ask extends. - #2826 (merged): accepted inline
system_promptonAgent— the file+kwargs form is its natural pair.
Alignment with the prompt-registry roadmap
#3914 + draft #3947 plan to deprecate the custom-Jinja fallback in favor of a typed prompt registry. If/when that lands, these profile fields can map onto registry entries (create_registry(...)) — we'd welcome that as the long-term home; the additive fields are the bridge that keeps server-side deployments prompt-capable meanwhile.
Environment
openhands-sdk / agent-server / tools / workspace 1.44.1 (pinned), re-verified against v1.46.0 sources (2026-09-10). Custom system_prompt_filename + ~10 system_prompt_kwargs rendered through the existing Jinja path, composed client-side today.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with sdk/settings/model.py:1365-1401 and sdk/profiles/agent_profile.py:122-187, then compare Agent field handling and validation in agent/base.py:207-262 and rendering at :346-373. Trace create_agent() and resolve_agent_profile() to see how profile values reach the composed Agent. Done means both profile/settings paths forward the filename and kwargs while preserving inline↔filename exclusivity.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100