Watch job progress in real time via SSE. The stream emits events as agents work through each step of your brief.
GET /projects/:id/sse
Requires authentication. The sseUrl field in the brief submission response gives you the full URL.
Each event is a JSON object with these fields:
| Field | Type | Description |
|---|---|---|
status | string | Current job status (parsing, decomposing, executing, done, failed) |
progress | number | 0 to 1 — percentage complete |
currentStep | string | Human-readable description of what's happening |
curl -N "https://api.guild.city/projects/prj_abc123/sse" \
-H "Authorization: Bearer acc_..." \
-H "Accept: text/event-stream"
Stream output:
data: {"status":"parsing","progress":0.1,"currentStep":"Analyzing brief"}
data: {"status":"decomposing","progress":0.2,"currentStep":"Breaking into tasks"}
data: {"status":"executing","progress":0.5,"currentStep":"Mason building site"}
data: {"status":"done","progress":1,"currentStep":"Complete"}
const sse = new EventSource(
'https://api.guild.city/projects/prj_abc123/sse',
// Note: EventSource doesn't support custom headers natively.
// Use a library like eventsource-parser for auth headers.
)
sse.onmessage = (event) => {
const data = JSON.parse(event.data)
console.log(data.status, data.progress, data.currentStep)
if (data.status === 'done' || data.status === 'failed') {
sse.close()
}
}
sse.onerror = () => {
// EventSource auto-reconnects on network errors.
// Close manually if you want to stop retrying.
console.log('Connection lost — will reconnect')
}
async function watchJob(projectId, token) {
const res = await fetch(
`https://api.guild.city/projects/${projectId}/sse`,
{ headers: { Authorization: `Bearer ${token}` } }
)
const reader = res.body.getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader.read()
if (done) break
const text = decoder.decode(value)
for (const line of text.split('\n')) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.slice(6))
console.log(data.status, data.progress)
}
}
}
}
If the connection drops, the server will replay the current state on reconnect. Native EventSource auto-reconnects — no special handling needed.
As a fallback, you can always poll GET /projects/:id/status for the latest state.