Skip to main content
Version: v2.4.0

Agents and Flows

The AI Optimizer uses Oracle AgentSpec to define its AI agents and flows as portable, serializable configurations. These configurations are loaded into LangGraph for execution.

What is AgentSpec?

AgentSpec is Oracle's Open Agent Specification. It provides a standard way to define two primary building blocks: Agents and Flows.

Agents are LLM-powered conversational assistants, optionally equipped with tools (e.g., the ReAct pattern). They are defined with a system prompt, an LLM configuration, and a set of tools.

Flows are structured DAGs (directed acyclic graphs) of connected nodes that form precise action sequences. Each node performs a specific task such as calling an LLM, invoking a tool, or branching on a condition, and edges wire them together.

AgentSpec configurations are pure data (JSON/YAML). They contain no executable code, which makes them portable across runtimes and safe to serialize, version, and share.

How They Work Together

Every agent in this project follows a three-stage pattern:

1. Define — AgentSpec Layer

Agent and flow definitions live in the agentspec/ package. This layer uses only pyagentspec SDK classes and produces portable configurations with no runtime dependencies.

Builder functions create the AgentSpec definitions:

Each builder takes the user's client settings (model provider, model ID, temperature, etc.) and constructs a complete AgentSpec definition.

2. Load — Runtime Loader

The runtime loader converts an AgentSpec definition into engine-specific objects. A plugin system handles custom components — for example, the LiteLLM plugin converts the AgentSpec LLM configuration into the appropriate model adapter.

For agents and flows that use MCP tools, the loader ensures the MCP transport is configured for API-key-based authentication.

3. Execute — Session Layer

Once loaded, agents and flows are executed through session objects that manage conversation state, chat history, and error handling.

Error Handling

All session objects catch exceptions raised during execution. When a flow or agent call fails:

  • The error is logged at ERROR level on the server.
  • The non-streaming chat API returns a 400 response for database connection errors, a 503 response for LLM configuration errors, and a 502 response with a cleaned error detail for other execution failures.
  • For agent sessions, failed turns are fully rolled back — the user message and any partial assistant messages are removed from conversation history, so subsequent turns are not corrupted.
  • For flow sessions, failed turns are simply not appended to history.

Prompt Fetching

All agents and flows attempt to fetch their system prompt from the MCP server. If the MCP server is unavailable, a hardcoded default instruction is used instead. This allows prompts to be managed externally without breaking the system.

Porting Specs to Your Own Application

AgentSpec definitions are pure data — they can be exported, modified, and loaded into any compatible runtime. The AI Optimizer exposes all its specs through a REST API so developers can inspect and reuse them.

Fetching Specs

EndpointDescription
GET /v1/agentspec/specsReturns all specs as serialized JSON
GET /v1/agentspec/specs/{name}Returns a single spec by name

Available specs:

NameTypeDescription
llm_onlyAgentLLM-only conversational agent (no tools)
nl2sql_agentAgentNL2SQL agent with a restricted SQLcl MCP tool inventory
vecsearch_flowFlowRAG pipeline: rephrase → retrieve → grade → answer

Loading a Spec in Your Application

Fetch a single spec, then deserialize its spec field:

from pyagentspec.serialization import AgentSpecDeserializer

from server.app.agentspec.adapters.litellm import get_litellm_deserialization_plugin

# The GET /v1/agentspec/specs/{name} response includes name, description, and spec.
deserializer = AgentSpecDeserializer(plugins=[get_litellm_deserialization_plugin()])
credentials = {
"<LLM config id>.api_key": "your-provider-api-key",
"<MCP transport id>.sensitive_headers": {"X-API-Key": "your-mcp-api-key"},
}
component = deserializer.from_dict(response["spec"], components_registry=credentials)

The list endpoint returns multiple responses in this same format, so select an item and pass its spec field to the deserializer.

Provider API keys are not included in exported specs. For models that require one, replace <LLM config id> with the LLM configuration's id and supply the key through components_registry before loading the component.

NL2SQL and VecSearch specs also omit MCP credentials. For each sensitive_headers $component_ref in the exported spec, add an entry keyed by that reference (instead of <MCP transport id>.sensitive_headers) that maps X-API-Key to the MCP server API key.

AgentSpec is runtime-agnostic — the same JSON can be loaded into LangGraph, WayFlow, CrewAI, AutoGen, or any other framework with an AgentSpec adapter.

Customizing Before Loading

Since specs are plain JSON/YAML, you can modify them before loading:

  • Swap the LLM provider — change provider and model_id in the LLM config to use OpenAI, OCI GenAI, or any LiteLLM-supported provider.
  • Change the MCP server — update the transport URL and headers to point to your own tool server.
  • Adjust prompts — edit system prompts, node instructions, or prompt templates to fit your domain.
  • Add or remove nodes — modify the flow DAG to add validation steps, logging, or custom branching logic.