Skip to main content

Common API tasks

These examples use curl and assume your API key is in an environment variable:

export FYAI_API_KEY=fyai_...
export AGENT=https://agent.fyai.co.nz
export CATALOG=https://catalog.fyai.co.nz

The key needs Write access for anything that creates or runs something. See Authentication. Everything you create lands in the key's project and appears in the web app straight away.

Create an agent​

An agent needs a model to run on. List the LLM configs available in your project and pick one:

curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/llmconfigs" | jq '.[] | {id, name, model, is_folder}'

Use an entry where is_folder is false. Then create the agent:

curl -s -X POST "$AGENT/agents" \
-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "Release Notes Writer",
"path": "/docs",
"system_message": "You turn lists of merged changes into short, plain-English release notes.",
"description": "Writes customer-facing release notes.",
"llm_config": 12,
"tags": ["docs"]
}'

name, path, system_message and llm_config are required. llm_config takes the config's ID or its exact name. The response is the full agent, including its id.

Optional fields you're likely to use:

FieldPurpose
functionsList of function IDs to give the agent as tools. You can also add them later with POST /agents/{id}/functions. See Adding tools to agents.
integration_idsIntegrations whose credentials the agent may use.
approval_modealways_require or never_require for tool-call approval. Leave it out to inherit.
memory_enabledtrue to give the agent memory across conversations.
repository_idsRepositories the agent works on. See GitHub repositories.
introduction_message, suggested_promptsWhat the agent shows before the first message in the web app.

Every agent setting is described in Agent settings. To change an agent later, PATCH /agents/{id} with only the fields you want to change.

Before running it, you can check the agent is runnable without calling the model:

curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/agents/42/readiness"
{ "ready": true, "reasons": [], "llm_config": { "id": 12, "model": "...", "is_platform_managed": true } }

If ready is false, reasons says why — usually a missing model credential.

Run an agent once​

For a quick, single-turn answer, call the synchronous endpoint:

curl -s -X POST "$AGENT/agents/42/run" \
-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
-d '{"message": "Write release notes for: fixed login timeout; added CSV export."}'
{
"output": "This release fixes…",
"agent_name": "Release Notes Writer",
"status": "completed",
"messages": [ … ],
"session_messages": [ … ],
"usage": { "input_tokens": 812, "output_tokens": 164, "total_tokens": 976, "cost_millicents": 0 },
"error_info": null
}
Request fieldPurpose
messageRequired. What you're asking the agent.
llm_config_override_idRun on a different LLM config for this call only.
prior_messagesEarlier turns, to continue a conversation. See below.
mission_idAttach the run to a mission.

output is the agent's final answer. usage is what the run was billed. When a run fails, error_info describes why (for example a model timeout or a context-length limit).

Synchronous runs hold the HTTP request open. If the agent uses tools or the answer is long, it can take longer than the ~100-second connection limit, so use the asynchronous version below.

Run an agent asynchronously​

Start the run:

curl -s -X POST "$AGENT/agents/42/run-async" \
-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
-d '{"message": "Review the open issues and summarise the top three risks."}'
{ "execution_id": "3f9c2a7e5b1d4c0e8a6f2b9d7c5e1a30", "status": "pending" }

Then poll every 15 seconds or so:

curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/agents/run-async/3f9c2a7e5b1d4c0e8a6f2b9d7c5e1a30"
statusMeaning
pendingStill running. Poll again.
completedresult holds the same object the synchronous run returns.
errorerror holds the failure message.

A finished result can be read repeatedly for about two hours, then it's removed. Only callers in the same organisation can read it.

Continue a conversation​

Agent runs are stateless. To ask a follow-up, pass the previous response's session_messages back as prior_messages:

import os, requests

agent = "https://agent.fyai.co.nz"
headers = {"X-API-Key": os.environ["FYAI_API_KEY"]}

first = requests.post(f"{agent}/agents/42/run", headers=headers,
json={"message": "Draft release notes for v2.3."}).json()

second = requests.post(f"{agent}/agents/42/run", headers=headers, json={
"message": "Make it shorter and add a heading.",
"prior_messages": first["session_messages"],
}).json()

print(second["output"])

Chat with a team​

A chat session is what the web app's Chat uses. Creating one over the API runs the first message in the background and records the whole conversation, so you can open it in the web app afterwards.

curl -s -X POST "$AGENT/chat/start" \
-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
-d '{
"chat_type": "group",
"team_configuration_id": 7,
"initial_message": "Research our three main competitors and compare their pricing.",
"start_run": true
}'
FieldPurpose
chat_typegroup for a team (with team_configuration_id), or agent for a single agent (with target_agent_id).
initial_messageRequired. The first message.
start_runSet true from code. Without it the session waits for a browser to connect and the message isn't processed.
llm_config_override_idFor single-agent chats only: use a different LLM config for this session.
is_autonomoustrue for a run with no human participant.

The response is the session, including its id. Then follow it:

# Is a run still executing?
curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/chat/1234" | jq '{status, run_alive, display_state}'

# The transcript so far
curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/chat/1234/conversations" | jq '.[] | {role, content}'

run_alive is true while a run is executing. display_state is one of running, failed, idle or done.

If the run stops to ask for a tool-call approval, answer it in the web app, or with POST /chat/{id}/approval and a body of {"approved": true} or {"approved": false}. To stop the run and end the session, call DELETE /chat/{id}/end.

note

Sending further messages into an existing chat session uses the web app's WebSocket protocol, which isn't documented as a public interface. For scripted multi-turn work, use agent runs with prior_messages.

Run a workflow and track it​

Every workflow run is tracked as a mission. Starting a run is two calls: create the mission in the catalog API, then ask the agent API to execute it.

  1. Find the workflow and the inputs it takes:

    curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/workflows" | jq '.[] | {id, name}'
    curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/workflows/88" | jq '.attributes'
  2. Optionally check it's ready to run:

    curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/workflows/88/validate"
  3. Create the mission. Put the workflow's inputs in attribute_values, keyed by attribute name:

    curl -s -X POST "$CATALOG/missions" \
    -H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
    -d '{
    "name": "Weekly competitor scan",
    "workflow_id": 88,
    "phase": "scoping",
    "mission_status": "active",
    "trigger_source": "api",
    "attribute_values": {"region": "APAC"}
    }'

    If the workflow takes no inputs, you can use POST /workflows/88/instantiate?trigger_source=api on the catalog API instead, which creates the mission for you.

  4. Execute it, using the mission's id:

    curl -s -X POST "$AGENT/workflows/execute" \
    -H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
    -d '{"workflow_id": 88, "mission_id": 5150, "initial_message": "Run the weekly scan"}'
    { "status": "started", "mission_id": 5150, "workflow_id": 88, "message": "Workflow execution started for mission 5150" }

    To run it in a specific execution environment, add execution_environment_id. See Execution environments.

  5. Poll the mission:

    curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/missions/5150" \
    | jq '{phase, mission_status, percent_completed, current_phase, total_tokens, total_cost}'
    FieldValues
    phaseexecuting while running; completed or failed when finished
    mission_statusactive (running), waiting_for_user (paused for an approval) or stopped
    percent_completed0 to 100
    current_phaseThe node currently running
    plan_stepsThe workflow graph. Each node's data.execution_status and data.resultPreview show its state and output.

    The run is finished when phase is completed or failed, or mission_status is stopped. You can also watch it under Missions in the web app.

  6. If the workflow has an approval gate, the mission pauses with mission_status waiting_for_user. List what's waiting and resolve it:

    curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/missions/node-approvals/pending"

    curl -s -X POST "$AGENT/workflows/missions/5150/node-approvals/31/resolve" \
    -H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
    -d '{"approved": true}'

    See Using approval gates.

tip

Start workflows with the X-API-Key header rather than a bearer token. A key lets the platform renew the run's credential, so runs longer than a few minutes don't fail partway.

To trigger workflows from other systems without writing code, use a webhook — see Triggering workflows with webhooks. To run on a timetable, see Scheduling workflows.

Load documents into a knowledge base​

  1. Create a knowledge base:

    curl -s -X POST "$CATALOG/knowledge-bases" \
    -H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
    -d '{"name": "Product handbook", "description": "Policies and how-tos"}'
  2. Add content. Plain text is stored straight away:

    curl -s -X POST "$CATALOG/knowledge-documents/ingest-text" \
    -H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
    -d '{"knowledge_base_id": 9, "title": "Refund policy", "content": "Customers can request a refund within 30 days…"}'
    { "stored_chunks": 3, "total_chunks": 3 }

    Other sources run in the background and return a job_id:

    EndpointBody
    POST /knowledge-documents/ingest-urlknowledge_base_id, url
    POST /knowledge-documents/ingest-gitknowledge_base_id, repo_url, optional branch (default main), path_filter (default **/*.md), subfolder, integration_id for private repositories. Needs Write.
    POST /knowledge-documents/ingest-confluenceknowledge_base_id, integration_id (or base_url, username, api_token), and space_key or parent_page_id
    POST /knowledge-documents/ingest-manifestknowledge_base_id, manifest_id (stored straight away)
    POST /knowledge-documents/uploadMultipart form with knowledge_base_id and file, up to 50 MB
    curl -s -X POST "$CATALOG/knowledge-documents/upload" \
    -H "X-API-Key: $FYAI_API_KEY" \
    -F knowledge_base_id=9 -F [email protected]
  3. Poll a background job:

    curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/knowledge-documents/ingest-jobs/$JOB_ID"

    status moves from queued to done (with stored_chunks) or error. Job status is held only briefly; if polling returns 404, check GET /knowledge-documents?knowledge_base_id=9 to see whether the documents arrived.

  4. Search it:

    curl -s -X POST "$CATALOG/knowledge-documents/search" \
    -H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
    -d '{"knowledge_base_id": 9, "query": "How long do customers have to ask for a refund?", "limit": 5}'

    Each result has the matching content, its source_type and source_ref, and a score.

GET /knowledge-bases/{id}/readiness tells you whether a knowledge base can be searched by meaning yet, and why not if it can't. For how knowledge bases work and how agents use them, see Knowledge bases and Setting up knowledge bases.