Agents
AI agents in Seclai are multi-step LLM pipelines that chain model calls, retrieval, validation, and actions together — with built-in retries, evaluation, governance, observability, and cost tracking at every step.
What are Agents?
Agents are AI-powered workflows that can:
- Call AI models (GPT, Claude, Gemini, and 200+ others) to generate responses
- Search knowledge bases using semantic similarity and metadata filters
- Transform and extract data from JSON, XML, and HTML
- Integrate with external systems via webhooks and APIs
- Send notifications via email
- Respond to incoming email — act as a virtual inbox that reads each message and replies to the sender, optionally remembering the conversation
- Run automatically on schedules or when content changes
- Store results in AWS S3 or display them directly
- Remember context across conversations using persistent memory banks
- Branch and merge parallel processing paths with gates and merge steps
Each agent is composed of ordered steps that execute as a directed graph, with outputs from one step feeding into the next. This creates powerful, flexible workflows for content processing and automation.
Agent Design Considerations
Before building an agent, it helps to decide where on the spectrum between deterministic pipeline and autonomous agent your use case falls. You can mix both styles in a single agent, and most production agents do.
Deterministic Pipelines
A deterministic pipeline uses explicit steps that run in a fixed order with known inputs and outputs. You define exactly what happens at each stage — which URL to fetch, which knowledge base to search, what template to apply. The model's job is limited to generating text from a well-scoped prompt.
Example — Daily news digest:
Trigger: Schedule (daily at 8 AM)
Step 1: Web Fetch → fetch https://example.com/feed
Step 2: Prompt Call → "Summarize the top 3 stories"
Step 3: Send Email → deliver to team@example.com
When to choose this approach:
- The inputs and data sources are known at design time
- Predictability matters more than flexibility — you want the same behavior every run
- You need to minimize token cost — the model only processes what you give it
- You want easy debugging — each step's input and output is visible in the trace
- The agent must work with models that don't support function calling
Autonomous (Agentic) Behavior
An autonomous agent uses tool-enabled prompt calls where the model decides what actions to take. The model can search the web, query knowledge bases, read documents, write to memory, and iterate — all driven by the prompt context rather than a fixed script.
Example — Research assistant:
Trigger: Dynamic Input
Step 1: Prompt Call (with web tools + KB tools) → "Research the user's
question. Search our internal docs and the web. Cite sources."
Step 2: Display Result → show the answer
When to choose this approach:
- The task is open-ended — you don't know which sources or queries will be needed
- The model needs to adapt its strategy based on what it finds (refine searches, follow links, try alternative queries)
- You want fewer steps to maintain — a single tool-enabled prompt call can replace a chain of explicit steps
Tradeoffs to consider:
- Higher token cost — tool calls and their results consume tokens across multiple rounds
- Less predictable — the model may skip tool calls or use them in unexpected ways
- Harder to debug — when the model makes a poor tool-calling decision, it can be less obvious than a failed explicit step
- Requires function-calling models — see Models for compatible options
Combining Both Approaches
Most production agents benefit from combining both styles. Use deterministic steps for the parts of the pipeline that are predictable (fetching a specific URL, loading a known document, writing to a fixed memory key) and tool-enabled prompt calls for the parts that benefit from model autonomy (analysis, synthesis, follow-up research).
Example — Content analysis with structured output:
Trigger: Content Added
Step 1: Load Content → load the new document (deterministic)
Step 2: Prompt Call (with memory tools) → "Analyze this document.
Check memory for prior context. Save key findings." (autonomous)
Step 3: Extract Content → extract the JSON analysis (deterministic)
Step 4: Send Email → deliver the structured report (deterministic)
Steps 1, 3, and 4 always run the same way. Step 2 adapts based on the document content and what it finds in memory.
For a detailed comparison of tools versus explicit steps — including a decision table for common scenarios — see Tools: Tools vs. Explicit Steps.
Agent Definition
An agent definition includes:
| Field | Type | Required | Description |
|---|---|---|---|
| Name | string | Yes | A descriptive identifier for the agent |
| Description | string | No | Details about the agent's purpose |
| Tags | array | No | Labels for organization and filtering |
| Steps | array | Yes | The ordered list of processing steps (must have at least one) |
Agent definitions are versioned via branches and changes, similar to version control. Each change captures a snapshot of the agent's full configuration including all steps and their settings.
Model Lifecycle Defaults
Agents can define lifecycle defaults for model-based steps:
prompt_model_auto_upgrade_strategy:none,early_adopter,middle_of_road, orcautious_adopterprompt_model_auto_rollback_enabled: enables rollback after configured failure signalsprompt_model_auto_rollback_triggers: subset ofagent_eval_fail,governance_flag,governance_block,agent_run_failed
These defaults apply to Prompt Call and Insight steps unless a step explicitly sets per-step overrides.
Precedence is:
- Step-level override
- Agent-level default
- System default
For field-level details and examples, see Agent Steps: Model Lifecycle Controls.
Configure these settings via the API or MCP:
curl -X PUT "https://api.seclai.com/api/agents/$AGENT_ID" \
-H "X-API-Key: $SECLAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt_model_auto_upgrade_strategy": "cautious_adopter",
"prompt_model_auto_rollback_enabled": true,
"prompt_model_auto_rollback_triggers": ["agent_eval_fail", "governance_block"]
}'
See Model Lifecycle: Automatic Model Upgrades for strategy descriptions and rollback behaviour.
Triggers
Triggers define when an agent runs and what input it receives. An agent can have multiple triggers, each with its own type, configuration, and optional schedule.
| Trigger Type | Input Source | Runs When |
|---|---|---|
| Dynamic Input | Provided at runtime | On-demand via API or UI |
| Template Input | Pre-defined template | On-demand or on schedule |
| Content Added | From new content | Automatically when content is added to a knowledge base |
| Content Updated | From updated content | Automatically when content changes in a knowledge base |
| Content Added or Updated | From new or changed content | Automatically on any content change |
| Email Received | An inbound email | Automatically when someone emails the agent's address — see Email Received |
All triggers support metadata — key-value pairs accessible in steps via {{metadata.field_name}}. Email-received runs also expose the sender, subject, and authentication results (e.g. {{metadata.email_from}}), so an agent can reply to the sender and hold a sustained conversation.
For complete trigger documentation, including scheduling, metadata examples, and use cases, see Agent Triggers.
Steps
Agents execute a series of steps in order. Each step type serves a specific purpose:
| Step Type | Description |
|---|---|
| Prompt Call | Call an AI model (200+ supported) to generate responses, with optional tools and structured JSON output |
| Generate Image | One-shot text-to-image generation (or image edit with reference attachments); you pick the model and size/aspect |
| Generate Audio | One-shot text-to-speech / audio generation; you pick the model, voice, and format |
| Generate Video | One-shot text-to-video (or image-to-video) generation; you pick the model, resolution, duration, and fps |
| Retrieval | Search a knowledge base using semantic similarity with optional reranking and metadata filters |
| Text | Produce output from a template with variable substitutions |
| Transform | Apply regex-based substitution rules to transform text |
| Gate | Evaluate conditions to control execution flow (continue or stop) |
| Merge | Combine outputs from parallel branches (named in wait_for) into a single result |
| Display Result | Mark output as the final visible result |
| Streaming Result | Stream LLM output tokens in real-time via SSE (Streaming Guide) |
| Extract Content | Extract JSON/XML/HTML from text and optionally convert format |
| Webhook Call | Make HTTP requests to external APIs |
| Write AWS S3 Object | Save content to an S3 bucket |
| Send Email | Send email notifications |
| Call Agent | Call another agent as a sub-workflow |
| Insight | Use an AI model with progressive-disclosure tools to analyze large input content |
| Evaluate Step | Score a previous step output and emit structured JSON (score, passed, pass_threshold) |
| Write Memory | Write content to a memory bank, partitioned by key (with optional speaker for conversation banks) |
| Search Memory | Search a memory bank using vector similarity, scoped by key |
| Load Memory | Load all memory entries for a key in chronological or reverse-chronological order |
| Write Metadata | Write a key-value pair to the agent run's metadata |
| Write Content Attachment | Write large content as an attachment to a content version |
| Load Content Attachment | Load a previously written content attachment |
| Retry | Re-execute from an ancestor step up to a maximum number of times |
| For Each | Iterate a body of steps over a runtime-resolved list, running the body once per item |
| If / Else | Evaluate gate-style conditions and dispatch to a then branch on match or an optional else branch |
| Switch | Dispatch on a single discriminator value to one of N named cases (with optional else default arm) |
| Human-in-the-Loop | Pause the run for a human approve/deny/custom-choice decision before continuing |
Steps support string substitutions using {{placeholder}} syntax to reference agent input, other steps' outputs, metadata, dates/times, and more.
For complete step documentation, including all fields, AI assistant support, and detailed examples, see Agent Steps.
Creating an Agent
Via the App
- Navigate to Agents in your account
- Click Create Agent and choose a creation mode:
- AI-assisted — Describe the agent, or pick an example for the assistant to adapt
- From an example — Pick an example from the gallery, searchable by use case (also browsable in Agent examples). Choose an existing resource for each one it uses, or have Seclai create the ones it can
- Blank — Start from an empty agent
- Configure the agent:
- Name — Give it a descriptive name
- Description — Optional details about its purpose
- Trigger Type — Select when it should run
- Add and configure steps
- Save and test
Via the API
Create agents programmatically using the API. See API Examples for code samples.
Running Agents
Manual Execution
Run agents on demand via the UI or API:
Via the UI:
- Open the agent
- Click Run on the trigger
- For dynamic input triggers: enter your input text and optional metadata
- For template input triggers: the template renders automatically
Via the API:
curl -X POST https://api.seclai.com/agents/{agent_id}/runs \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": "What are the latest AI trends?",
"metadata": {
"user_id": "123",
"source": "api"
}
}'
Automatic Execution
Agents run automatically when:
- Scheduled triggers fire at the configured time(s) — see Schedules
- Content triggers detect changes in the connected knowledge base — see Content Triggers
File Attachments
Agents with a dynamic_input or email_received trigger accept file attachments alongside text input — the files its declared attachments accept. A file no step reads or converts reaches steps as a file only. Before Seclai-Version: 2026-10-16, /api accepts only the types its endpoint description lists. Size limit: 200 MB per file (5 MB for SVG).
For the full conceptual model — where attachments come from, how to reference them between steps, and worked examples (uploads, generated images, per-file fan-out) — see the dedicated Attachments guide. This section covers the upload / API / MCP flow and how a run's files are checked against the trigger's declared attachments.
SVG uploads are sanitized at write time (and re-sanitized at every serve) to strip <script>, event-handler attributes (onclick, onload, ...), <foreignObject>, javascript: / data:text/... URIs in href / xlink:href, and CSS expression() / behavior: payloads. Animation elements (<animate>, <set>) are unconditionally dropped because they can target attributeName="onclick" and inject a script payload. The cleaned SVG retains shapes, gradients, filters, text, and inline raster data:image/... references; everything else is removed. SVG bytes that can't be parsed as XML at all are rejected with an upload error.
An upload is ready as soon as it is stored. Each step receives the file itself when its model reads that type — images, PDFs, audio or video on the models that take them. A step whose model cannot read it receives it converted — an image to PNG or JPEG, a file to its text (OCR, document extraction, or an audio/video transcript), or a PDF with no usable text to images of its pages — made once and reused by every later step. A file's text is scanned for prompt injection and screened by your governance input policies before any step reads the file, natively or converted; a Redact policy that changes that text sends the redacted text in place of the file. When reading a file's text fails, a step whose model reads the file itself fails, and a step that would need it converted runs without it and records a warning.
The agent-input-binary janitor deletes uploaded files once your account's agent-trace retention period has passed.
Via the UI
In the Run Agent modal, switch to the Attach files tab, which lists the attachments the trigger accepts. Drop one or more files onto the upload area or pick them with the file button; previews appear inline. The "Run Agent" button waits until every file has finished uploading — a run either carries all of them or none.
Attached files belong to the run, not to the tab: they stay listed (and stay in the run) if you switch back to Text input, so you can re-read your prompt without losing them.
The message box stays visible on that tab, and whatever you type there is sent with the files — so "here is a photo, what is wrong with it?" is one run. Your text leads and each file follows under a # {filename} heading, all reachable as {{agent.input}} / {{input}}, and each file reaches steps as an attachment, through the placeholders described below. Leave the message empty to send the files alone.
Via MCP
Two-step flow:
- Upload —
upload_agent_input(agent_id, filename, content_b64, content_type)stores the file and returns{upload_id, status, ...}withstatus="ready". - Run —
run_agent(agent_id, input_upload_id=...)for a single file, orrun_agent(agent_id, input_upload_ids=[...])for multiple. Passinputas well to send prompt text with the files.
Via the API
# 1. Upload the file
UPLOAD_ID=$(curl -X POST https://api.seclai.com/agents/{agent_id}/upload-input \
-H "X-API-Key: YOUR_API_KEY" \
-H "Seclai-Version: 2026-10-16" \
-F "file=@./invoice.pdf" \
-F "content_type=application/pdf" \
| jq -r .id)
# 2. Trigger the run referencing the upload
curl -X POST https://api.seclai.com/agents/{agent_id}/runs \
-H "X-API-Key: YOUR_API_KEY" \
-H "Seclai-Version: 2026-10-16" \
-H "Content-Type: application/json" \
-d "{\"input_upload_id\": \"$UPLOAD_ID\", \"input\": \"Which line items are billable?\"}"
For multiple files, pass input_upload_ids: [...] instead.
input and input_upload_id(s) are not mutually exclusive — send both when the run is "a file plus a question about it". The prompt text leads and each file follows under a # {filename} heading, so the whole thing is one {{agent.input}} value; the files reach steps as attachments. Only input_upload_id and input_upload_ids conflict with each other — they are two spellings of the same batch.
Before Seclai-Version: 2026-10-16, each file's extracted text is written under its heading. A file is ready when the upload responds unless it is a scanned PDF that needs OCR or a recording that needs a transcript; it then reports status="processing" until that text is made — poll GET /agents/{agent_id}/input-uploads/{upload_id} until ready before running.
Referencing attachments in steps
By default, steps see attachments only when their template declares the dependency:
- Referencing
{{input}},{{agent.input}}, or{{step.<id>.input|output}}brings in all attachments carried on that source (implicit visibility). - Use
{{attachments[…]}}selectors inside text fields (prompt templates, email HTML body, S3 object key, …) to narrow the set — by index ({{attachments[0]}}), filename glob ({{attachments[*.pdf]}}), or exact filename ({{attachments[invoice.pdf]}}).
Steps that consume files (send_email, write_aws_s3_object, write_cloud_drive_file, webhook_call, call_agent, publish_content, write_content_attachment, for_each, display_result, streaming_result, add_chat_turn) expose a dedicated Attachments config field — a list of {{…}} reference expressions. Each expression selects attachments by source and form: this step's input ({{attachments[…]}}), the agent input files ({{agent.attachments.<name>}} for one declared attachment, {{agent.attachments}} for all), or a specific upstream step's output files ({{step.<id>.attachments[…]}}). Multiple expressions union their matches in list order, deduplicated by (source, step_id, storage_key):
{
"attachments": ["{{attachments[*.pdf]}}", "{{attachments[*.csv]}}"]
}
LLM-call steps (prompt_call, evaluate_step, extract_data) route attachments via inline {{attachments[…]}} placeholders in their prompt fields, or via an Attachments list, which replaces the files their templates reference. (call_agent is a file-consuming step and uses the dedicated Attachments list field above to choose which files to forward to the sub-agent.)
See File Attachments in the Agent Steps reference for the full grammar, multi-modal routing rules, and per-step behaviour.
Upload & run validation
The trigger's declared attachments drive three gates so an upload mismatch surfaces as a clear error rather than a silently ignored file:
- Editor save — placing
{{attachments[…]}}on a non-consumer step type (text, gate, transform, …) or{{step.<id>.attachments[…]}}against a step type that can never output files (aweb_search,if_else,extract_content, …) is rejected at save time with a field-level error pointing at the offending placeholder. So is an{{agent.attachments.<name>}}naming an attachment the trigger does not declare (undeclared_attachment). - Upload time — a file no declared attachment accepts is rejected by
upload_agent_input(MCP) andPOST /agents/{id}/upload-input(REST) withagent_does_not_accept_uploads/ HTTP 400, so a user doesn't upload a file the run would refuse. - Run time — the batch passed to
run_agentis assigned to the declared attachments: every file must fit one, and each attachment must receive at least itsminfiles. A batch that doesn't fit is refused with HTTP 400 and a message listing each problem, such as'Invoice' needs at least 1 file (application/pdf); 0 received.
Attached files are also scanned. Each text file the run starts with is scanned in parallel with the input, and any unsafe one flips the run's input scan to UNSAFE and blocks downstream LLM-calling steps; the Input Scan pseudo-step surfaces an attachments_scanned count alongside the main verdict. Any other file is converted to text, and that text is scanned and screened by your input policies before a step reads the file in any form, natively included: a jailbreak embedded in an uploaded PDF fails the step that reads it. Fail-closed semantics: if a per-attachment scanner call fails (transient outage, network error), the run is marked UNSAFE rather than silently skipping the unscanned file.
Discovering an agent's declared attachments
Both MCP and the external API return the trigger's declared attachments so you can stage uploads that fit on the first try:
- MCP:
get_agent_attachment_references(agent_id)— returns{requires_uploads, accepted_attachments, agent}.requires_uploadsisfalsewhen the agent has no Dynamic Input trigger, or that trigger declares no attachments;accepted_attachmentslists each one'sname,label,content_types,name_pattern,minandmax. Call this beforeupload_agent_input/run_agent. - REST:
GET /agents/{agent_id}/attachment-references— same shape and semantics.
Downloading attachments emitted by a run
Attachments produced by a step (image-generation, transcripts, generated PDFs) are accessible to external consumers via an authenticated download endpoint:
GET /v2/agent-runs/{run_id}/attachments/{attachment_id}
You rarely build this URL yourself: a run's status (GET /agents/runs/{run_id} and the MCP get_agent_run_status tool) lists the files in its output as attachments: [{id, name, mime, bytes, download_url}], and each step's files the same way when step outputs are requested. A run made before attachments existed may list none there; on the REST API its files are still named in output on a Seclai-Version earlier than 2026-09-30.
Text and files are separate. A step's output is its text, and its files are listed beside it. In a template, {{step.<id>.output}} and {{input}} are the text of a step that also produced files (empty when it produced only files), and {{step.<id>.attachments}} are its files. A run's and a step's output on run status is that text. On the REST API this applies from Seclai-Version: 2026-09-30; an earlier version is still sent the JSON envelope {schema, text, attachments: [{storage_key, mime, name, label, bytes}]} as output whenever the output has files. See API versioning.
- Auth: dual-auth — send
X-API-Keyor OAuth Bearer (same pattern as the rest of/api). attachment_id: the file'sidfromattachments. Links in webhook payloads and emails use the URL-safe base64-encodedstorage_keyinstead; both forms are accepted.- MIME handling: inline-safe MIMEs (
image/*,audio/*,video/*,application/pdf,text/plain,application/vnd.seclai.manifest+json) are served with their declared type; everything else gets forced toapplication/octet-streamwith an attachmentContent-Dispositionto prevent stored-XSS. - 404, never 403: a run your account does not own, a file that is not in the run, and a run whose trace was deleted under your retention window all return 404, and another account's run is indistinguishable from one that does not exist.
File names. In an agent created in the app, files a step generates are named from the agent's structure, so they are the same on every run: gen.1.png is the first file step gen generated, gen.2.1.png the first one it generated for the second item of a for_each, and research.chart.1.png a file a call_agent step research returned from its child agent. Files a step receives keep their source's name under the step, fetch.photo.png for photo.png, with fetch.photo~2.png for a second file of the same name; those are only as stable as the source and the order it lists them in. Agents created before this, or through the API without the definition's file_names: "structural", keep the names the model or source gave their files. Uploaded files always keep their names; one named like a step's file shares that name, and a selector matches both. These are the names recipients see and the names {{attachments[…]}} selectors match. A name or pattern selector that matches none of a source's files, when that source has some, adds a warning to its step, shown in the run trace and in the step's warnings on run status.
Users who need public URLs (e.g. embedding generated images in a public webpage) must download via this endpoint and re-host elsewhere — Seclai does not emit unauthenticated download URLs.
Webhook attachment delivery modes
webhook_call steps with payload_shape = json_with_urls (the default for multi-asset outputs) emit per-attachment metadata as {name, mime, url, bytes}. The URL shape is controlled by attachment_url_mode:
presigned_s3(default) — 1-hour presigned AWS S3 URLs. Receivers don't need a Seclai API key; bandwidth bypasses the Seclai API; URL expires after 1 hour and is not revocable. Best for low-trust short-lived consumers.seclai_auth— URLs hit/v2/agent-runs/{run_id}/attachments/{attachment_id}on the Seclai API. Receivers MUST send X-API-Key or a Bearer token belonging to the same account as the agent. No expiry; revocable by rotating the API key; every fetch is logged. Best for audited integrations or receivers that already hold a key.
json_with_base64 and multipart_form payload shapes are unaffected — they inline the bytes directly.
Email attachment delivery (CID + URL fallback)
send_email step HTML bodies can reference attachments inline:
<img src="{{attachments[0]}}" alt="generated chart" />
<img src="{{step.gen.attachments[*.png]}}" />
When a <img src="{{attachments[…]}}"> reference resolves to an image attachment, the step handler:
- CID-embeds the image (under a 10 MB per-image cap and a 20 MB cumulative inline budget per email) by converting the placeholder to a
data:image/X;base64,…URI which the email sender's existing MIME pipeline turns into amultipart/relatedinline part. Recipients see the image inline regardless of their email client's "block remote images" setting. - URL-rewrites images that exceed either cap (or attachments that aren't images) to an
https://api.seclai.com/v2/agent-runs/…/attachments/…link — recipients click → authenticate → see the file. Email recipients are always Seclai org members so the OAuth flow is available to them. - Drops any single attachment that exceeds the 25 MB SES per-message envelope entirely (the email would be rejected by SES anyway) and logs an
EMAIL_ATTACHMENT_DROPPED_OVERSIZEDactivity event.
Each CID embed and URL rewrite emits its own activity event (EMAIL_ATTACHMENT_CID_EMBEDDED / EMAIL_ATTACHMENT_URL_REWRITTEN) with the count and total bytes so reports can split inline-vs-URL usage.
Surfacing attachments in display_result / streaming_result
display_result and streaming_result are also attachment-consumer steps: when their input carries files, or attachments selects some, those files become the step's files and so the run's. The step's output stays its text. The trace viewer renders the files inline below the text, so generated images / audio / PDFs surface at the agent's terminal exactly the way they surface on a prompt_call output.
Streaming token SSE events are unaffected — clients still see text streaming live; the files appear on the trace and on run status once the stream completes.
S3 step path + key split
write_aws_s3_object splits its destination into two fields:
object_path(optional) — folder prefix. May reference run-level substitutions ({{agent.run_id}},{{datetime UTC}}) but not per-attachment placeholders ({{name}},{{index}},{{ext}}) — those belong onobject_keyso each attachment writes to a distinct filename within the same path.object_key— the filename portion. For multi-asset prompt outputs include{{name}},{{index}}, or{{ext}}so each attachment writes to a distinct key. Without a placeholder, a multi-asset input is rejected at runtime to prevent silent overwrites.
The final S3 key is {object_path}/{object_key} (joined with a single /) when object_path is set, else just {object_key}. Legacy object_key strings containing a / are auto-migrated on save: the last / separates path from key.
Monitoring Runs
Run Status
Each agent run has a status:
| Status | Description |
|---|---|
| Pending | Queued for execution |
| Processing | Currently running |
| Completed | Finished successfully |
| Failed | Error occurred during execution |
Step Runs
Each step within a run tracks:
- Status — Pending, processing, completed, or failed
- Input and output — The data flowing in and out of the step
- Error messages — Details if the step failed
- Duration — How long the step took to execute
- Credit usage — Credits consumed by the step (for AI model calls)
Agent Traces
Agent traces are per-run execution records that show what happened during a run from start to finish. They include status, step-level inputs and outputs, errors, timing, and credit usage.
You can find them here:
- UI: Account → Agents → [Agent Name] → Traces tab
- API:
GET /agents/{agent_id}/runs
The primary purpose of traces is operational visibility. Use them to debug failures, validate outputs, diagnose performance bottlenecks, and monitor reliability over time. Traces also support searching across past runs so you can quickly find specific results.
For complete details and best practices, see Agent Traces.
Agent Warnings
The system analyzes your agent definition and provides warnings for:
- Missing required metadata fields referenced in substitutions
- Undefined step references (e.g.,
{{step.nonexistent.output}}) - Invalid model selections
- Configuration issues that could cause runtime failures
Warnings appear in the agent editor and help you fix issues before deployment.
Validation
Agents are validated at save time (not just at execution) so a definition cannot be persisted if it has any of:
- Missing required fields (e.g.,
modelonprompt_call,knowledge_base_idonretrieval) or invalid enum values (e.g.,convert_to: "json"onextract_content— onlyhtml,markdown, orplain_textare valid). - Step references (
{{step.X.output}}) that point at parallel siblings or descendants. Only strict ancestors and join-reachable branches are addressable. - Aggregating
for_eachloops with no downstream consumer of{{step.<for_each_id>.output}}— the aggregated array would silently drop. - A merge
wait_foror retry target in a differentfor_eachbody (or outside the loop, from inside it); anevaluate_steptarget inside a loop body the step is not in, or the loop the step is in; and.item/.item_indexof a loop used outside it. - Memory steps targeting a memory bank of the wrong type (
add_chat_turnon a general bank,add_memoryon a conversation bank, etc.). chat_historyinput on aprompt_callwhose parent isn't anadd_chat_turnorload_chat_history.streaming_resulton an agent without a user-input trigger (dynamic_inputortemplate_input).- Cycles in the step graph.
- Step nesting deeper than the cap or text fields beyond the per-field size limit.
Validation errors are returned with per-field paths (e.g.
agent.child_steps[0].prompt_call.model) so the editor can point the user
straight to the offending field. The same checks run on the visual editor
save path, the bulk-update API, the patch API, and the AI-assistant-driven
writes from generate_agent_steps.
Alerts
Configure alerts to be notified when agent runs match specific criteria. Alerts can monitor run outcomes and trigger notifications based on conditions you define.
Exporting Agents
Export an agent's full definition as a portable JSON snapshot. The export includes the complete step workflow, trigger configuration with schedules, alert configs, and a dependency manifest that resolves every referenced external entity (knowledge bases, memory banks, source connections, other agents, users) to its human-readable name.
What's included in the export:
export_version— schema version for forward compatibilityexported_at— ISO-8601 timestampsoftware_version— application version that produced this exportagent— name, description, schema version, full definition, timestampstrigger— trigger type, input template, and schedules (if any)alert_configs— alert type, thresholds, and recipients (if any)evaluation_criteria— evaluation settings per step (if any)governance_policies— agent-scoped governance policies (if any)dependencies— grouped lists of knowledge bases, memory banks, source connections, agents, and users referenced by the definition
How to export:
- UI (detail page): Click the Export button in the agent header.
- UI (list page): Open the agent's action menu (⋮) and select Export.
- Public API:
GET /api/agents/{agent_id}/exportwith your API key. - MCP: Use the
export_agenttool with the agent ID.
The export is a read-only snapshot — it does not modify the agent.
Round-trip: A previously exported agent JSON can be re-imported as-is via the UI's Import button or the create/update API endpoints — see Importing Agents below.
Other export types: You can also export an agent's trace history and evaluation results as bulk data files in JSON, JSONL, or CSV. See Export Formats for all available export types.
Importing Agents
Re-import a previously exported agent definition to create a new agent (or apply the workflow + metadata to an existing one). The import accepts the same JSON shape that Export produces, so a round-trip is supported out of the box.
Forward compatibility: The import schema is intentionally lenient — unknown top-level fields (e.g. ones added by a newer software version) are silently ignored, and most optional fields can be omitted. The minimum payload is a top-level agent object containing a definition; everything else is optional. This means an export from a newer Seclai deployment usually still imports cleanly into an older one.
What gets applied on create:
agent.definition— the full step workflow becomes the new agent's initial workflow.agent.*metadata —description, evaluation tier/mode, retry settings, sampling, and prompt-model auto-upgrade/rollback fields fill in any value you didn't override on the create call.trigger— input template, content type, metadata, and any schedules attached to the trigger.evaluation_criteria— only criteria whosestep_idexists in the imported workflow.alert_configs— alert type, thresholds, recipients. Recipients are resolved by user UUID first; if that fails (importing across accounts) the export'sdependencies.usersblock is used to fall back to email-based lookup. Recipients that match neither are skipped with a server-side warning.governance_policies— agent-scoped policies. Knowledge-base associations are matched by name in the target account; unknown names are skipped.
What does not happen on update: alert configs, evaluation criteria, and governance policies are intentionally not touched on update — they have their own dedicated endpoints to avoid silently destroying state. Updates do still:
- Apply agent metadata fields the request didn't set explicitly.
- Replace the workflow from
agent.definition. The previous version is preserved in history; nothing is overwritten in place.
Validation errors include line/column references against a canonical pretty-printed echo of your payload, plus a path and a human-readable message — Pydantic's raw vocabulary is intentionally never exposed. The 422 response body looks like:
{
"detail": {
"error": "invalid_agent_definition",
"message": "Invalid agent definition payload.",
"errors": [
{
"line": 7,
"column": 19,
"path": "agent.definition.child_steps[0].step_type",
"message": "Field 'step_type' has an invalid value (expected one of [...])."
}
],
"source": "<canonical pretty-printed JSON of the payload>"
}
}
(The shown object is the contents of detail. The HTTPException raised by the FastAPI endpoint wraps it under that key on the wire.)
The line and column are 1-indexed and reference the canonical pretty-printed rendering returned in source, so they're stable regardless of how the original JSON was formatted.
Workflow validation errors (cycles in the step graph, invalid prompt-call tooling, depth/text-length caps, etc.) raised at save time return a similar 422 under detail: {error, message, validation_errors:[{field, message, code, line, column}], source}. The shape mirrors parse-time errors so callers can render line/column-precise feedback the same way: when the request supplied an agent_definition, the router anchors each entry's line/column against the canonical pretty-printed echo (returned in source); when no import payload was supplied, line/column default to 1 and source is the empty string. Each entry also carries field (a dotted path like agent.definition.child_steps[0].id) and an optional stable code. The UI's import modal handles both envelopes uniformly via frontend/app/utils/agent-import-error.ts::normaliseImportFailureDetail.
Cross-account portability: When importing an export from a different account, workflow entity references (knowledge bases, memory banks, source connections, sub-agents called by call_agent steps) won't match by UUID. The preview endpoint scans the workflow and returns unresolved_refs — one entry per unmatched reference, each with the available alternatives of the same type in the target account. Pass entity_remap: {source_uuid: target_uuid} on the create/update call to substitute them before save:
{
"name": "Imported",
"trigger_type": "dynamic_input",
"agent_definition": { "agent": { "definition": { ... } } },
"entity_remap": {
"11111111-1111-1111-1111-111111111111": "<target-account-kb-uuid>"
}
}
When a category has zero alternatives in the target account (e.g. you're importing a workflow that uses a knowledge base but the target account has no KBs at all), the UI blocks the import until you create the missing resource. Create the resource first, then re-import. The API will still accept the request if you omit the remap, but the agent will fail at runtime when it tries to dereference the original UUID.
Alert recipients still fall back to email-based lookup via the export's dependencies.users manifest. Governance KB attachments still match by name. In both cases, items that can't resolve are skipped and surfaced via import_warnings (see below).
Change log on commit (import_warnings): every successful create/update response that involved an agent_definition payload includes an import_warnings array. Each entry has {category, message, details} and explains one part of the payload that was not applied exactly as submitted. Categories: schedule, evaluation_criteria, alert_config, alert_recipient, governance_policy, governance_kb_link, solution_link — all of which mean the item was dropped or defaulted — plus json_template, which means an advanced prompt payload was rewritten into the selected model's own format and persisted in the rewritten form (nothing was lost; details.step_path points at the step). Empty array means the payload was applied verbatim; field omitted entirely means no import happened on that call.
How to import:
- UI (list page): Click Import in the agents list header, pick the file, optionally rename. If the workflow references resources that don't exist in this account, the modal shows a picker for each unresolved reference; choose substitutes (or cancel and create the missing resources first), then click Import as new agent. After commit, any items that were skipped are listed in a yellow notice that you must dismiss before the modal closes.
- UI (existing agent): Click Import on the agent detail page. Update only replaces the workflow + agent metadata — alert configs, evaluation criteria, governance policies, schedules, and solution links from the imported file are not applied. The modal warns you when the imported file carries any of those sections.
- Public API (preview):
POST /api/agents/preview-importwith{"agent_definition": {...}}returns the summary plusunresolved_refs. Use this to drive a remap UI before committing. - Public API (commit):
POST /api/agents(orPUT /api/agents/{id}) with{"name": "...", "trigger_type": "...", "agent_definition": {...}, "entity_remap": {...}}. The response includesimport_warnings. - MCP: Use the
preview_agent_importtool to validate and discover unresolved refs, thencreate_agent(orupdate_agent) with the sameagent_definitionplusentity_remap.
AI Assistants
Seclai provides AI assistants that help you build and refine agent workflows from natural language. All assistants follow a propose-then-accept pattern: you describe what you want, the assistant generates a plan or configuration, and you review and accept or decline it. The assistant never makes changes without your approval.
Workflow Generator
Generates a complete multi-step agent workflow from a natural language description.
Access: Open the agent editor and click Generate with AI, or describe what you want when creating a new agent.
What it generates:
- The full step graph with correct step types, ordering, and branching
- Prompt templates and system templates for each prompt call
- Retrieval configurations (knowledge base selection, top_n, search queries)
- Memory steps wired to the correct memory banks
- Gate conditions, extract content queries, webhook configurations
- Model selections appropriate for each step's complexity
Example prompts:
- "Build a customer support chatbot that uses my Product Information KB and remembers user preferences"
- "Create an agent that monitors news, summarizes daily, and emails the digest to team@example.com"
- "Make an email inbox agent that answers questions sent to it from my Product Information KB and replies to the sender, remembering each sender's conversation"
- "Build an agent with parallel branches — one searches the KB, one fetches a web page — then combines both results"
Tips for best results:
- Describe the outcome, not the implementation. Say "answer product questions from my docs" instead of "create a retrieval step then a prompt_call step."
- Name resources by name. Use "my Product Information knowledge base" instead of UUIDs — the assistant resolves names automatically.
- Describe the full pipeline in one prompt. The assistant handles branching, ordering, and wiring when it can see the whole picture.
- State constraints up front. "Use Haiku for classification and Sonnet for the summary to keep costs low" works better than correcting after.
See Prompt Best Practices for guidance on the prompt templates the generator creates.
Step Configurator
Refines the configuration of an individual step after the workflow has been generated or manually created. Each step type has a tailored assistant.
Access: Open any step in the agent editor and click the AI Assistant button (sparkle icon).
Supported step types:
| Step Type | Configuration Help |
|---|---|
| Prompt Call | System/prompt templates, model selection, temperature, tools |
| Gate | Condition expressions, pass/fail routing |
| Extract Content | JSONPath/CSS/XPath queries, format selection |
| Text Transform | Regex patterns, replacement strings, templates |
| Retrieval | Search queries, top_n tuning, knowledge base selection |
| Send Email | Recipient lists, subject/body templates |
| Memory steps | Key expressions, speaker fields, query strings |
| Call Agent | Agent selection, input mapping |
| Context Compactor | Summary instructions, token limits |
Example prompts:
- "Change this prompt call to return JSON with fields: topic, severity, and summary"
- "Set up a gate that passes when the sentiment score is above 0.7"
- "Write a regex that extracts email addresses from the input"
MCP tools: generate_agent_steps (workflow generator), generate_step_config (step configurator). See MCP Server.
For general best practices on getting the most from all AI assistants, see AI Assistant Best Practices.
Example Workflows
RAG Chat Bot
A customer support bot that answers questions using your documentation:
Trigger: Dynamic Input
Step 1: Retrieval — Search documentation knowledge base
Step 2: Prompt Call — Generate answer using retrieved context
Step 3: Display Result — Show the answer
Content Monitor
Monitor RSS feeds and send email summaries of new articles:
Trigger: Content Added (on news knowledge base)
Step 1: Prompt Call — Summarize the new article
Step 2: Gate — Only continue if article is relevant
Step 3: Send Email — Deliver the summary
Scheduled Report
Generate a daily analysis report from your knowledge base:
Trigger: Template Input (daily schedule at 8 AM)
Template: "Generate daily report for {{date America/New_York}}"
Step 1: Retrieval — Fetch recent content
Step 2: Prompt Call — Analyze and generate report
Step 3: Write AWS S3 Object — Store the report
Step 4: Send Email — Deliver the report
Parallel Analysis Pipeline
Run multiple analyses in parallel and combine results:
Trigger: Dynamic Input
Step 1: Retrieval — Search knowledge base
├── Step 2a: Prompt Call (summarize)
└── Step 2b: Prompt Call (extract entities)
Step 3: Merge (wait_for: [2a, 2b]) — combine summary and entities
Step 4: Write AWS S3 Object — Store combined result
Step 5: Display Result — Show to user
Next Steps
- Agent Traces — Understand run-level observability, debugging, and monitoring
- Agent Triggers — Deep dive into trigger types, schedules, and metadata
- Agent Steps — Comprehensive reference for all step types
- Knowledge Bases — Connect data sources to agents
- Memory Banks — Give agents persistent memory across conversations
- Content Sources — Learn about content sources for knowledge bases
- API Examples — Code samples for agent automation