feat(client): add SubAgentsClient for POST /api/sub-agents#253
Conversation
Add a client for the agent-server's read-only POST /api/sub-agents endpoint, which lists the file-based and built-in sub-agents (delegate agents) available to a workspace. The endpoint mirrors POST /api/skills and was missing from the TypeScript client. - SubAgentsClient.getSubAgents(request) posts to /api/sub-agents - SubAgentsRequest / SubAgentInfo / SubAgentsResponse types mirror the server's lossless AgentDefinition view (all frontmatter fields plus level, source, is_builtin, and the inline system_prompt) - Expose manager.subAgents on ConversationManager; export the client and types from clients.ts and index.ts - Unit tests for request/response mapping and the default empty body - Integration test that discovers a project-level sub-agent end-to-end
Endpoint audit❌ 6 off-contract call(s) — not on the agent-server · classifiers: cloud
❌ Not on agent-server (gated, 6)⛔ (no known backend) — served by no backend we can see (5)
|
|
@OpenHands why did the CI fail? “HttpError: HTTP request failed (500 Internal Server Error): {"detail":"Internal Server Error","exception":"500: Failed to activate profile"}” /codereview |
|
I'm on it! enyst can track my progress at all-hands.dev |
|
I checked the failed What happened:
So the CI failure is not from Likely fixes: create the test agent file through the agent-server/workspace path as the container user, or explicitly make/chown/chmod the host-created This comment was created by an AI agent (OpenHands) on behalf of the user. |
…y test
The project-level sub-agent discovery test writes
`.openhands/agents/<name>.md` into the workspace from the host (the
test runner). Its cleanup only unlinked the agent file, leaving the
`.openhands/` directory behind, owned by the host user.
The agent-server container runs as a different user, so a later test
(profile round-trip) failed when the server tried to chmod
`workspace/.openhands` during profile activation:
Failed to set permissions on workspace/.openhands:
[Errno 1] Operation not permitted
-> 500 Failed to activate profile
Add a `removeWorkspacePath` helper and use it to remove the whole
`.openhands` tree the test creates, restoring the workspace so the
server can create and own `.openhands` itself.
|
@enyst if you have time :) |
|
🚀 Released in v1.32.0. |
Summary
The agent-server exposes a read-only
POST /api/sub-agentsendpoint (added in software-agent-sdk #3911, released in v1.31.0) that lists the file-based and built-in sub-agents (delegate agents) available to a workspace. It mirrorsPOST /api/skills. This endpoint was missing from the TypeScript client — this PR adds it.What's included
SubAgentsClient(src/client/sub-agents-client.ts) withgetSubAgents(request)→POST /api/sub-agents, following the same shape asSkillsClient/PluginsClient.src/models/api.ts):SubAgentsRequest,SubAgentInfo,SubAgentsResponse, andSubAgentLevel.SubAgentInfois a lossless mirror of the server'sAgentDefinitionview — every frontmatter field plus the discoveredlevel/source,is_builtin, and the inlinesystem_prompt.manager.subAgentsonConversationManager(constructed + closed alongside the other clients); exported fromclients.tsand the model types fromindex.ts.Tests
api-clients.test.ts):manager.subAgentsnamespace assertion; request/response mapping to/api/sub-agents(incl. API-key header, fullSubAgentInfopayload); default empty-body behavior.deterministic-api.integration.test.ts):getSubAgents(builtin discovery), asserting the contract shape.Verification
npm test— 273 unit tests pass.ghcr.io/openhands/agent-server:1.31.0-pythonimage (the project-level discovery test confirms the endpoint end-to-end). Note: the frozen image ships no built-in agent files, so the builtin path returns an empty list — the assertions account for this.tsc --noEmit,eslint, andprettier --checkall clean.