Docs
ReferencePython SDK

Custom agents

View Markdown

An Agent is a custom assistant users build for an app: a prompt, optional model selection, tabular context, backend API tools, and optional analysis/chart capabilities. Define one exported Agent(...) declaration in Python. This is separate from the coding agent implementing the project and the React conversation manager displaying it.

Declaration and defaults

Agent(
    provider: "openai" | "anthropic" | None = None,
    model: str | None = None,
    prompt: str = "",
    context: list[Table | TransformOutput] = [],
    tools: list[ApiRunner] = [],
    capabilities: AgentCapabilities = AgentCapabilities(),
)
AgentCapabilities(
    sql_analysis: bool = False,
    chart_generation: bool = False,
)

The SDK creates fresh context/tool lists and capabilities per instance. Provider and model may be omitted for platform defaults. Set an explicit model only when that provider/model is available in your deployment. Unknown Agent fields are rejected. Agent has no name property; identity comes from the registered resource name or ID used in CLI and React calls.

Write a concrete prompt describing purpose, available data/tools, decision rules, expected response structure and how to handle missing evidence or execution failures. Describe the configured tools and data so the assistant knows what it can use. Keep secrets out of prompts, source and user-visible results.

Context and API tools

  • Table("connector.sync") declares synced tabular context.
  • Table("_upload.customers") declares an uploaded table named customers. _upload is reserved and cannot name a connector.
  • TransformOutput("transform") declares a single published transform output.
  • TransformOutput("transform.output") selects one named published output.
  • Only Table and TransformOutput are supported in Python Agent.context. DatabaseTable, Database, Input, Secret and File are not Agent context types.
  • Uploaded documentation is platform-managed context outside the Python declaration. Attach documents through the managed upload workflow below.
  • ApiRunner("api_resource_name") declares an API tool. It is a resource reference, not a direct HTTP client, a Python function or an arbitrary callable wrapper.

Discover actual resources and API input/response contracts before planning tools. Declaring context does not create a missing table or run an upstream transform. The platform binds tools to runtime resources; constructing a runner locally does not bind it. A bound runner.run(inputs: dict | None = None) invokes the configured API with scalar runtime inputs and returns its response. SDK-level api_id/client binding arguments are runtime plumbing; customer declarations should use names, not private clients or embedded UUID mappings. Tools resolve through the platform's execution mode: preview selects committed API versions and preview data, while deployed runs select deployed API versions and production data. The runtime pins selected API tool versions for the turn.

from vortexify import Agent, AgentCapabilities, ApiRunner, Table, TransformOutput

assistant = Agent(
    prompt=(
        "Help operators understand customer orders. Use available tables and tools "
        "to substantiate answers. Ask for a customer ID when it is needed. "
        "If a tool fails or data is missing, explain the limitation without inventing results."
    ),
    context=[Table("shopify.orders"), TransformOutput("customer_totals")],
    tools=[ApiRunner("customer_orders")],
    capabilities=AgentCapabilities(sql_analysis=True),
)

Resource names are illustrative; use existing resources and the project plan. The parser reads declarative constructors rather than executing arbitrary Python to discover the definition; keep declarations statically readable. The platform parses this declaration into resource metadata when source is saved; the Python file remains the versioned source of the definition.

Capabilities

Both capabilities are off by default. Enable SQL analysis when the assistant needs to answer questions from its declared data, and chart generation when it should propose visualizations of those answers.

sql_analysis exposes context-scoped table inspection and analyze_table_data, using isolated DuckDB jobs. Poll with job_id alone; query_id is the resulting analysis job ID. Start with query and tables=[{"alias": "orders", "table_id": "id-from-list_tables"}]; SQL reads the provided aliases. Only the saved agent version's declared context tables can be analyzed. chart_generation exposes generate_chart(query_id, chart_name, chart_config). It references a completed analysis without rerunning SQL. Chart config uses chartType (Bar, StackedBar, GroupedBar, Line, MultiLine, Scatter, Pie), xKey and yKeys. Charts require a complete result with at most 1000 rows. Apps read the chart tool result and fetch stored JSON rows with client.getAnalysisData(query_id). See analysis charts for rendering. Chart references must belong to the same saved agent version. Enable sql_analysis as well when the agent needs to create the analyses it will chart. Enable only capabilities required by the task and supported by the runtime. Inspect the resulting analysis or tool execution when verifying the interaction.

React integration and verification

An app uses useVortexify() and agentManager.consume(client.runAgent("order_assistant", {message, data, actions})). See React conversations and actions for selection, bounded data snapshots, stream state, and frontend actions. Frontend execute functions stay in the browser; only action names/descriptions/schemas and timeoutMs reach the backend. The SDK submits AgentToolResult ({success, message?, data?}; message required on failure), and the agent waits for that actual result. Errors and timeouts are failures; a timeout means browser outcome is unknown. When get_current_view_context is available, request it for fresh page context after navigation or changes. Initial application data.current_view is a bounded snapshot, not a continuously live view.

Verify the assistant by trying a question that needs one of its declared tables or API tools, then inspect the saved conversation and tool results. In the platform, Conversations provides this history, Files lists attached documents, and Code exposes the saved declaration. Transform/API vxfy_test decorators do not define Agent tests.

Attach searchable documentation

Uploaded PDF, TXT, and Markdown documents are managed attachments rather than Python Agent.context entries. Create and implement the custom agent first, then upload and commit:

vortexify upload file ./operations.md --resource-type agent --resource order_assistant --wait --json
vortexify files agent order_assistant --json
vortexify commit --type agent --resource order_assistant

The saved agent version's attachments supply document-search and bounded-preview tools at runtime. No extra SDK context type or capability flag is required. An attachment to a connector is not automatically an attachment to a custom agent. CLI files commands show bounded beginning-text previews; full-document search is not a CLI command today. See CLI attachments.

See add an assistant for the app workflow.

Python SDK 0.1.1 removes the name property from Agent. Identity comes from the registered resource name or ID used by the CLI and React SDK. Remove name= from existing declarations and update requirements.in to vortexify==0.1.1 when upgrading.