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 90+ 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
- 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, joins, and combinators
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 |
All triggers support metadata — key-value pairs accessible in steps via {{metadata.field_name}}.
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 (90+ supported) to generate responses, with optional tools and structured JSON output |
| 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) |
| Combinator | Merge outputs from parallel branches into a single result |
| Join | Connect a parallel branch to a combinator |
| 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, producing one step run 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
- Configure the agent:
- Name — Give it a descriptive name
- Description — Optional details about its purpose
- Trigger Type — Select when it should run
- Knowledge Base — (Optional) Connect to a knowledge base
- Template — Start with blank or use a retrieval example
- 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 trigger accept file attachments alongside text input. Supported types: text, PDF, DOCX/PPTX/XLSX, images (PNG, JPEG, GIF, BMP, TIFF, WebP, SVG), audio (MP3, WAV, M4A, FLAC, OGG), video (MP4, MOV, AVI). Size limit: 200 MB per file.
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.
Each upload flows through two parallel channels:
- Native binary — multi-modal LLMs (Claude, Gemini, Nova, GPT-4o-class) see the raw bytes
- Extracted text — every file is OCR'd / transcribed (audio/video via AssemblyAI, documents via MarkItDown / Tesseract). Text-only models see this content; the prompt scanner and governance evaluators always see this content regardless of which channel the model uses
Audio originals are preserved past transcription so audio-capable models (Gemini 2.5/3, GPT-5 audio) read them directly; the agent-input-binary janitor sweeps blobs past AGENT_INPUT_BINARY_RETENTION_DAYS (default 30 days).
Via the UI
In the Run Agent modal, click the file-upload affordance below the input text area. Drop one or more files; previews appear inline. The "Send" button enables once the uploads finish processing.
Text input typed into the same modal is still available as {{agent.input}} / {{input}}; uploaded files reach the steps via the attachment placeholders described below.
Via MCP
Two-step flow:
- Upload —
upload_agent_input(agent_id, filename, content_b64, content_type)stages the file and returns{upload_id, status, ...}. Text and document files come backstatus="ready"immediately; audio/video are submitted to AssemblyAI and start asstatus="processing"— pollget_agent_input_upload_status(upload_id)until ready. - Run —
run_agent(agent_id, input_upload_id=...)for a single file, orrun_agent(agent_id, input_upload_ids=[...])for multiple.
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" \
-F "file=@./invoice.pdf" \
-F "content_type=application/pdf" \
| jq -r .id)
# 2. (Audio/video only) poll until status=ready
curl https://api.seclai.com/agents/{agent_id}/input-uploads/$UPLOAD_ID \
-H "X-API-Key: YOUR_API_KEY"
# 3. 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 "Content-Type: application/json" \
-d "{\"input_upload_id\": \"$UPLOAD_ID\"}"
For multiple files, pass input_upload_ids: [...] instead.
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 manifest input (send_email, write_aws_s3_object, webhook_call, call_agent, publish_content, write_content_attachment, for_each, display_result, streaming_result) expose a dedicated Attachment Rules config field — a structured list of selection rules. Each rule combines a source (input, agent, or step + step_id) with a kind (all, index, or pattern) and emits the matching attachments. Multiple rules union their matches in rule order, deduplicated by (source, step_id, storage_key):
{
"attachment_rules": [
{ "source": "input", "kind": "pattern", "pattern": "*.pdf" },
{ "source": "input", "kind": "pattern", "pattern": "*.csv" }
]
}
LLM-call steps (prompt_call, call_agent, evaluate_step, extract_data) route attachments via inline {{attachments[…]}} placeholders in their prompt fields (no rule-list field — the placeholder grammar is what triggers media-block routing). Legacy single-string attachments selectors on consumer steps are auto-migrated to a single-entry rule list on the next save.
See File Attachments in the Agent Steps reference for the full grammar, multi-modal routing rules, and per-step behaviour.
Upload & run validation
Saved agents carry a static attachment-reference contract computed from every consumer step's templates. The contract drives 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 that doesn't produce a multi-asset manifest (onlyprompt_callandcall_agentdo) is rejected at save time with a field-level error pointing at the offending placeholder. - Upload time — when an agent's definition declares no attachment references at all,
upload_agent_input(MCP) andPOST /agents/{id}/upload-input(REST) reject withagent_does_not_accept_uploads/ HTTP 400 so a user doesn't waste cycles uploading files that will never be consumed. The Run Agent modal hides the "Attach files" toggle entirely in this case. - Run time — when the agent declares attachment references, the batch passed to
run_agentmust satisfy them: every exact filename ({{attachments[invoice.pdf]}}) must appear in the batch; the highest declared index ({{attachments[2]}}) must be in range; every glob pattern ({{attachments[*.pdf]}}) must match at least one filename. Unmet selectors fail the run with HTTP 400 and a message listing the missing requirements.
When the agent does require uploads, the Run Agent modal renders a hint block listing the expected filenames, the minimum file count for indexed references, and any required patterns so users know what to upload before they hit the file picker.
Attached files are also scanned in parallel: every upload's extracted text flows through the prompt-injection scanner on its own thread, and any single unsafe attachment (a jailbreak embedded in an uploaded PDF, for example) flips the run's input scan to UNSAFE and blocks downstream LLM-calling steps — closing the previous text-only blind spot on the safety layer. The Input Scan pseudo-step in the run trace surfaces an attachments_scanned count alongside the main verdict so you can confirm at a glance that uploads were screened. 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 attachment contract
Both MCP and the external API expose the agent's static attachment-reference contract so you can stage uploads that satisfy it on the first try:
- MCP:
get_agent_attachment_references(agent_id)— returns{requires_uploads, agent: {kinds, indexes_max, exact_names, patterns}}. Call this beforeupload_agent_input/run_agentso you know whether the agent accepts files at all, and what specific filenames/indexes/patterns the templates reference. - REST:
GET /agents/{agent_id}/attachment-references— same shape and semantics.
The frontend Run Agent modal calls this automatically on open and uses the response to hide the "Attach files" toggle (when requires_uploads === false) or render expectation hints (filename list, minimum file count, glob patterns).
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 /api/v2/agent-runs/{run_id}/attachments/{attachment_id}
- Auth: dual-auth — send
X-API-Keyor OAuth Bearer (same pattern as the rest of/api). - Scoping: the calling account must own
run_id; cross-account access returns 403. attachment_id: the URL-safe base64-encodedstorage_keyof the attachment as it appears in a step output manifest within the run (the encoder is shared by the webhook + email payload builders, so the URLs they emit round-trip cleanly).- 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 vs 403: the server validates that the storage_key is referenced by some step output in the run before responding, so guessing keys cross-tenant returns 404 (not 403).
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/api/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/api/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: setting attachment_rules on either makes the step emit a multi-asset manifest (application/vnd.seclai.manifest+json) instead of plain text. The trace viewer's StepOutputManifest component renders the attachments inline via the existing media-preview machinery, so generated images / audio / PDFs surface at the agent's terminal exactly the way they surface on a prompt_call output today.
Streaming token SSE events are unaffected — clients still see text streaming live; the manifest only appears on the trace as the step's persisted output after the stream completes.
Atomic attachment-rule mutations (MCP + REST)
The full-definition update_agent_definition (PUT the entire JSON) is fine for editor saves, but for one-rule changes — especially from an LLM that doesn't want to round-trip the whole agent JSON — a focused set of CRUD endpoints exists:
- REST:
GET /api/agents/{agent_id}/steps/{step_id}/attachment-rules— list current rules + change_id.POST /api/agents/{agent_id}/steps/{step_id}/attachment-rules—{rule, position?}— insert atposition(or append).PUT /api/agents/{agent_id}/steps/{step_id}/attachment-rules/{rule_index}—{rule}— replace by index.DELETE /api/agents/{agent_id}/steps/{step_id}/attachment-rules/{rule_index}— remove by index; later rules shift down.PUT /api/agents/{agent_id}/steps/{step_id}/attachment-rules/order—{new_order: [...]}— bulk reorder via a permutation list.POST /api/agents/{agent_id}/steps/{step_id}/attachment-rules/preview—{rules?, sample_attachment_names?}— dry-run validation + per-rule match resolution against a sample; never mutates.
- MCP: corresponding tools
list_agent_step_attachment_rules,add_agent_step_attachment_rule,update_agent_step_attachment_rule,remove_agent_step_attachment_rule,reorder_agent_step_attachment_rules,preview_agent_step_attachment_rules.
Each mutating call routes through the same validator the editor's full PUT uses (Pydantic schema → step-graph checks → placeholder + rule-reference checks), so no surface can bypass validation by routing around the editor. Validation failure surfaces in the REST 422 detail as a structured array — {rule_index, field, code, message, suggestion} per failing rule plus an other_validation_errors bucket for cross-step issues; MCP tools return the same shape inline in the response.
Every successful mutation creates a new AgentBranchChange row (one per call) so the audit trail stays linear and reverts are surgical.
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. - 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).
Skip 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 an item that was dropped or had a default substituted. Categories: schedule, evaluation_criteria, alert_config, alert_recipient, governance_policy, governance_kb_link, solution_link. Empty array means nothing was skipped; 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"
- "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) → Join → Combinator
└── Step 2b: Prompt Call (extract entities) → Join → Combinator
Step 3: Combinator — Merge 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