The Service Contract
Your service answers one HTTP endpoint. This page describes that endpoint, what Neo sends it, and what Neo expects back. How your agent produces its answer is entirely up to you.
The Endpoint
POST {Agent Service URL}/run?stream=true|false
Content-Type: application/json
The platform appends /run to the Agent Service URL you registered and sets a single query parameter:
|
Behaviour |
|---|---|
|
Return one complete JSON response. Neo passes your JSON back to the caller unchanged. |
|
Stream the answer. Neo forwards what you write, as you write it, to the waiting client. |
Implement /run and handle both values of the parameter.
The Request Body
{
"input": "What is my account balance?",
"agent_id": "3f9a1c72-5e44-4b18-9c1e-7d2a6b0f8e51",
"session_id": "9b7e2d10-4c3f-4a56-8f21-1e6c5b90a3d7",
"internal_user_id": "priya@example.com",
"config": {}
}
Field |
Always sent |
Meaning |
|---|---|---|
|
Yes |
The user’s message. An empty string if the caller sent no input. |
|
Yes |
The Neo Code Agent’s own identifier in Neo — the same ID that appears in the page URL. |
|
Yes |
Identifies the conversation. Use it to group turns and to correlate your logs with the platform’s records. |
|
No |
The signed-in user’s email address. Omitted entirely when the caller has no email — for example an API-key request. Never assume this key is present. |
|
No |
Whatever the caller passed as |
Treat unknown or missing optional keys defensively — read config and internal_user_id with a default rather than indexing them directly.
Responding
Non-streaming (stream=false) — reply 200 with a JSON body. The shape is yours to define; Neo returns it to the caller as-is without inspecting or reshaping it.
Streaming (stream=true) — reply 200 and write the answer as you generate it. Neo reads your response bytes as they arrive and re-emits each chunk to the client as a token event, then sends a final end event when your response closes. Because Neo forwards raw bytes, write plain incremental text rather than your own event envelope.
Errors and Timeouts
Condition |
What the caller sees |
|---|---|
Your service returns a non-200 |
The same status code, with your response body in the error detail. Return meaningful status codes and readable messages. |
Neo cannot connect at all |
502 Bad Gateway. Usually a wrong URL, a DNS failure, or a service that is down or unreachable from the platform. |
No response within 300 seconds |
The request is abandoned. Five minutes is the ceiling for a single turn; stream long answers so the caller sees progress. |
Securing Your Endpoint
Neo sends the request with Content-Type: application/json as its only header, so secure an External URL service at the network layer:
Place the service on a private network reachable only by the platform.
Restrict inbound traffic to the platform’s egress addresses — ask your platform administrator for these.
Put a gateway or proxy in front of it that applies your own authentication before traffic reaches the agent.
Use
internal_user_idto personalise a response, not to authorise one. It arrives as an unsigned value in the request body.
With an EKS Deployment, the container runs inside the platform’s cluster and its address is not published externally. Supply any secrets your agent needs through Environment Variables on the deployment configuration — see Creating a Neo Code Agent.
A Minimal Implementation
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
app = FastAPI()
@app.post("/run")
async def run(request: Request, stream: bool = False):
body = await request.json()
user_input = body.get("input", "")
session_id = body.get("session_id")
user_email = body.get("internal_user_id") # may be absent
config = body.get("config", {}) # may be absent
answer = await my_agent(user_input, session_id, config, user_email)
if stream:
async def chunks():
for piece in answer_pieces(answer):
yield piece # plain text, no envelope
return StreamingResponse(chunks(), media_type="text/plain")
return {"output": answer}
Exposing /openapi.json — as FastAPI does automatically — lets the builder’s API endpoints panel list your operations when you click Fetch, which is a quick way to confirm you have registered the right URL.
Checklist Before Registering
1 |
|
2 |
The |
3 |
Missing |
4 |
Responses complete well within 300 seconds, or stream. |
5 |
The URL is reachable from the platform and secured at the network layer. |
6 |
Failures return a meaningful status code and a readable message. |