Skip to main content

Agents and Flows

The AI Optimizer is an agentic platform built around Oracle AgentSpec and LangGraph. AgentSpec defines the reusable agents and flows as portable, serializable configurations; LangGraph loads those definitions for execution. MCP supplies the tools, prompts, and resources that the runtime exposes to clients and agent routes.

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​

The reusable AgentSpec components follow 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.

The Chatbot also provides a combined route that classifies each request and coordinates the NL2SQL Agent and Vector Search Flow at runtime. That router is intentionally runtime orchestration rather than an exported AgentSpec component; see Combined Router.

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 runtime sessions 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​

Each route fetches its system prompt from the MCP server. If the MCP server is unavailable, a factory default instruction is used instead. This lets prompts be managed externally while keeping the runtime available when the prompt service cannot be reached.

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 Vector Search 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.