Core domain type definitions for the Embabel Agent Framework, providing foundational data classes and interfaces for agent-based AI workflows including content assets, research entities, and person types with Jackson serialization and PromptContributor capabilities.
Domain models for working with news content in agent workflows.
Represents a news story with URL, title, and summary.
open class NewsStory(
override val url: String,
val title: String,
override val summary: String
) : PromptContributor, PageProperties:
url: String - News story URL (from Page)title: String - News story titlesummary: String - Story summary (from Page)Interfaces:
PromptContributor - Provides contribution(): String for LLM promptsPage - Web page with url and summaryMethods:
contribution(): String - Returns formatted news story (Title, Summary, URL)Note: Open class - can be extended with additional properties.
Container for multiple news stories.
open class RelevantNewsStories(
val items: List<NewsStory>
) : PromptContributorProperties:
items: List<NewsStory> - List of news storiesInterfaces:
PromptContributor - Provides contribution(): String for LLM promptsMethods:
contribution(): String - Returns joined contributions from all stories, or "No relevant news stories found." if emptyNote: Open class - can be extended.
import com.embabel.agent.domain.library.NewsStory
val story = NewsStory(
url = "https://example.com/news/ai-breakthrough",
title = "Major Breakthrough in AI Agent Planning",
summary = "Researchers developed a new planning algorithm improving agent decision-making."
)
// Access properties
println(story.url) // URL
println(story.title) // Title
println(story.summary) // Summaryimport com.embabel.agent.domain.library.RelevantNewsStories
import com.embabel.agent.domain.library.NewsStory
val newsStories = RelevantNewsStories(
items = listOf(
NewsStory(
url = "https://example.com/story1",
title = "AI Agents Transform Enterprise",
summary = "Companies report efficiency gains..."
),
NewsStory(
url = "https://example.com/story2",
title = "New Planning Algorithm Released",
summary = "GOAP-based planning shows promise..."
),
NewsStory(
url = "https://example.com/story3",
title = "Spring AI Integration",
summary = "Framework integration improves DX..."
)
)
)
// Access stories
newsStories.items.forEach { story ->
println(story.title)
}val story = NewsStory(
url = "https://tech.example.com/quantum",
title = "Quantum Computing Milestone",
summary = "IBM announces 1000-qubit processor"
)
val contribution = story.contribution()
// Returns:
// Title: Quantum Computing Milestone
// Summary: IBM announces 1000-qubit processor
// URL: https://tech.example.com/quantum
val prompt = """
Consider this news:
${story.contribution()}
What are the implications?
""".trimIndent()val news = RelevantNewsStories(items = listOf(...))
val allNews = news.contribution()
// Returns:
// Title: AI Agents Transform Enterprise
// Summary: Companies report efficiency gains...
// URL: https://example.com/story1
//
// Title: New Planning Algorithm Released
// Summary: GOAP-based planning shows promise...
// URL: https://example.com/story2
//
// Title: Spring AI Integration
// Summary: Framework integration improves DX...
// URL: https://example.com/story3val emptyNews = RelevantNewsStories(items = emptyList())
val contribution = emptyNews.contribution()
// Returns: "No relevant news stories found."
// Use in logic
if (emptyNews.items.isEmpty()) {
println("No news to report")
} else {
println(emptyNews.contribution())
}val allStories = RelevantNewsStories(
items = listOf(
NewsStory("https://ex.com/1", "AI Breakthrough", "New algorithm..."),
NewsStory("https://ex.com/2", "Cloud Security", "Best practices..."),
NewsStory("https://ex.com/3", "Agent Planning", "GOAP improvements...")
)
)
// Filter by keyword
val aiStories = RelevantNewsStories(
items = allStories.items.filter { "AI" in it.title || "Agent" in it.title }
)
// Top N stories
val topStories = RelevantNewsStories(
items = allStories.items.take(2)
)
// Transform summaries
val enhanced = RelevantNewsStories(
items = allStories.items.map { story ->
NewsStory(
url = story.url,
title = story.title,
summary = "${story.summary} [More: ${story.url}]"
)
}
)import java.time.Instant
class CategorizedNewsStory(
url: String,
title: String,
summary: String,
val category: String,
val publishDate: Instant,
val source: String
) : NewsStory(url, title, summary) {
override fun contribution(): String =
super.contribution() +
"\nCategory: $category\nSource: $source\nDate: $publishDate"
}
val story = CategorizedNewsStory(
url = "https://example.com/tech-news",
title = "New AI Framework",
summary = "Framework for building agents...",
category = "Technology",
publishDate = Instant.parse("2026-02-06T10:00:00Z"),
source = "TechCrunch"
)import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
val mapper = jacksonObjectMapper()
// Single story
val story = NewsStory(
url = "https://example.com/article",
title = "Breaking News",
summary = "Important developments..."
)
val json = mapper.writeValueAsString(story)
val deserialized = mapper.readValue(json, NewsStory::class.java)NewsStory JSON Format:
{
"url": "https://example.com/article",
"title": "Breaking News",
"summary": "Important developments..."
}RelevantNewsStories JSON Format:
{
"items": [
{
"url": "https://ex.com/1",
"title": "Title 1",
"summary": "Summary 1"
},
{
"url": "https://ex.com/2",
"title": "Title 2",
"summary": "Summary 2"
}
]
}import com.embabel.agent.domain.library.*
// Agent finds news stories
fun findNewsStories(topic: String, count: Int): RelevantNewsStories {
// Real agent would use web search
val stories = listOf(
NewsStory(
url = "https://example.com/news1",
title = "Latest in $topic",
summary = "Recent developments..."
),
NewsStory(
url = "https://example.com/news2",
title = "$topic Trends",
summary = "Industry experts predict..."
)
).take(count)
return RelevantNewsStories(items = stories)
}
// Use in agent
val aiNews = findNewsStories("AI Agents", 5)
// Generate summary with LLM
val prompt = """
Based on these news stories:
${aiNews.contribution()}
Summarize key trends.
""".trimIndent()
// Process result
if (aiNews.items.isNotEmpty()) {
// Process with LLM...
} else {
println("No news found")
}fun createBlogFromNews(
news: RelevantNewsStories,
author: String
): Blog {
val content = news.items.joinToString("\n\n") { story ->
"## ${story.title}\n\n${story.summary}\n\n[Read more](${story.url})"
}
return Blog(
title = "This Week in AI",
author = author,
content = "# Latest News\n\n$content",
keywords = setOf("news", "ai", "weekly")
)
}fun enrichResearchWithNews(
report: ResearchReport,
news: RelevantNewsStories
): String {
return """
${report.contribution()}
## Recent News
${news.contribution()}
""".trimIndent()
}fun summarizeNews(stories: RelevantNewsStories): Summary {
if (stories.items.isEmpty()) {
return Summary("No news available")
}
val topics = stories.items.joinToString(", ") { it.title }
return Summary("News covering ${stories.items.size} stories: $topics")
}tessl i tessl/maven-com-embabel-agent--embabel-agent-domain@0.3.0