Skip to main content
Add custom endpoints when your application needs a business-specific HTTP contract in addition to Harnest’s neutral API. The same extension works with managed or advanced ADK and LangGraph agents.

Add an endpoint

Create a synchronous route factory in the root agent’s lifecycle/ directory. Harnest injects an AgentInvoker and mounts the returned FastAPI router.
lifecycle/http.py
The factory can return multiple routes or use FastAPI dependencies. Define route factories only at the root. SubAgents do not own server paths.

Invoke the agent safely

AgentInvoker uses the same response coordinator as POST /responses. It does not call the raw ADK or LangGraph object.
Pass the current FastAPI Request as connection. Do not accept or construct a user_id from the request body.
After authenticating the request, your route can derive an invocation-specific tool surface:
The principal is optional. Omitting it preserves the existing unrestricted tool surface. Supplying one activates default-deny behavior: untagged capabilities and capabilities without a matching grant are unavailable. An empty principal therefore makes every Harnest-governed capability unavailable. Do not accept permission names directly from the request body. See Agent Runtime Principals for propagation and Advanced-mode coverage. For a security-sensitive deployment, require grants on every custom agent invocation:
config.yaml
With this setting, a custom route that omits agent_principal= fails before session creation instead of restoring the root agent’s unrestricted surface.

Handle required actions

An invocation can pause instead of returning a final answer:
Resume human approvals through POST /approvals/{approvalId}. Submit browser-hosted tool results through POST /client-tools/{requestId}. These endpoints share the same suspended execution created by the custom route. Use response.as_dict() when your endpoint should return Harnest’s complete neutral response shape unchanged.

Add an application-specific session view

Keep business dimensions such as site origin, workspace, inbox, or project out of the neutral /sessions contract. Add an authenticated custom endpoint and query an application-owned index instead:
lifecycle/http.py
site_sessions represents your indexed projection or repository, not a Harnest type. Update it when a session is associated with an origin and scope its index by the authenticated user_id. This provides complete server-side filtering and global ordering without teaching Harnest about one application’s domain model.
Do not fetch one bounded /sessions page and filter it locally. Matching sessions may exist on later pages, and sorting a page is not the same as sorting the complete filtered result.

Route ownership

Compilation rejects duplicate routes and Harnest-owned namespaces. Reserved paths include /responses, /sessions, /live, /approvals, /client-tools, /agent, /healthz, playground assets, OpenAPI pages, and ADK-native run or application routes. When you configure authentication, custom routes are protected by default. They also appear in /openapi.json. Harnest does not currently provide streaming through AgentInvoker; use the neutral SSE or WebSocket APIs when you need streaming. See Neutral API, Approvals and client tools, and Authentication and credentials.