Agents
All agents implement the Agent trait which defines a single method:
trait Agent {
def chat(message: String): String
}
This simple interface allows agents to be easily composed and used as tools within other agents.
One Shot Agent
A stateless agent that executes a single request-response cycle with a fixed system prompt. Useful for specific tasks or as a tool within other agents.
val agent = OneShotAgent(
systemPrompt = "You are a helpful assistant. Respond concisely.",
completionClient = ChatCompletionClient()
)
val response = agent.chat("What is 2+2?")
The completionClient parameter defaults to ChatCompletionClient(), so it can be omitted for standard usage.
Creating Task-Specific Agents
The OneShotAgent.forTask factory helps create agents for specific tasks:
val summarizer = OneShotAgent.forTask(
taskName = "Text Summarization",
taskDescription = "Summarize the given text in one sentence.",
inputFormat = Some("Raw text"),
outputFormat = Some("One sentence summary")
)
val text = "Artificial intelligence has made tremendous progress. " +
"AI systems are becoming increasingly capable in many domains."
val summary = summarizer.chat(text)
Variable Substitution
The execute method supports template variables:
val template = "Generate a {style} greeting for {name}."
val result = agent.execute(
template,
Map("style" -> "formal", "name" -> "Dr. Smith")
)
RAG Agent
A Retrieval-Augmented Generation agent that uses a vector store to retrieve relevant documents and include them as context when answering questions.
val vectorStore = new InMemoryVectorStore()
val embeddingClient = new EmbeddingClient()
val documentIndexer = new DocumentIndexer(embeddingClient, vectorStore)
// Index documents
val documents = List(
("doc1", "Scala is a strong statically typed programming language..."),
("doc2", "The JVM enables running Java programs...")
)
documentIndexer.indexDocuments(documents)
// Create RAG agent
val ragAgent = new RagAgent(
completionClient = ChatCompletionClient(),
embeddingClient = embeddingClient,
vectorStore = vectorStore,
topK = 3,
maxTurns = 10
)
val answer = ragAgent.chat("What is Scala?")
The agent:
- Embeds the query using the embedding client
- Searches the vector store for the top K relevant documents
- Constructs a system message with the retrieved context
- Passes the context and query to the LLM
Vector Store
The VectorStore trait defines the interface for document storage and retrieval:
trait VectorStore {
def add(id: String, content: String, embedding: List[Double]): Unit
def addAll(documents: List[(String, String, List[Double])]): Unit
def search(queryEmbedding: List[Double], topK: Int = 5): List[ScoredDocument]
def get(id: String): Option[Document]
def remove(id: String): Unit
def clear(): Unit
}
The included InMemoryVectorStore implementation uses cosine similarity for search.
Conversational Agent
A stateful agent that maintains conversation history across multiple interactions.
val agent = ConversationalAgent()
val response1 = agent.chat("I have an orange cat named Whiskers.")
val response2 = agent.chat("What color was it?")
// Response will remember the cat is orange
Conversation State
Conversation history is managed by the ConversationState trait:
trait ConversationState {
def get: List[ChatMessage]
def update(messages: List[ChatMessage]): Unit
}
The default InMemoryState implementation keeps the most recent messages:
val conversationState = new InMemoryState(maxMessages = 50)
val agent = ConversationalAgent(
conversationState = conversationState
)
Agents as Tools
Agents can be used as tools within other agents using Agent.deriveAgentTool:
// Create a specialized agent
val calculatorAgent = OneShotAgent(
systemPrompt = "You are a calculator. Perform arithmetic accurately."
)
// Derive a tool from the agent
val calculatorTool = Agent.deriveAgentTool(
calculatorAgent,
agentName = Some("calculator"),
description = "Use this tool to perform arithmetic calculations"
)
// Register the agent tool
val toolRegistry = ToolRegistry()
.register(calculatorTool)
// Use in another agent
val mainAgent = OneShotAgent(
systemPrompt = "You are an assistant. When asked to do math, use the calculator tool.",
toolRegistry = Some(toolRegistry)
)
val response = mainAgent.chat("What is 100 divided by 4?")
This enables agent composition and specialization, where complex tasks can be delegated to domain-specific agents.
Next Steps
- Learn about the Tool system
- Explore Security policies for safe tool execution
- Browse Provided tools