Migrating from other frameworks

Many people start their journey with Python frameworks.

This section covers how to migrate from popular frameworks when it’s time to use a more robust and secure platform with access to existing code and services.

Migrating from CrewAI

CrewAI uses a collaborative multi-agent approach where agents work together on tasks. Embabel provides similar capabilities with stronger type safety and better integration with existing Java/Kotlin codebases.

Core Concept Mapping

CrewAI ConceptEmbabel EquivalentNotes
Agent Role/Goal/BackstoryRoleGoalBackstory PromptContributorConvenience class for agent personality
Sequential TasksTyped data flow between actionsType-driven execution with automatic planning
Crew (Multi-agent coordination)Actions with shared PromptContributorsAgents can adopt personalities as needed
YAML ConfigurationStandard Spring @ConfigurationProperties backed by application.yml or profile-specific configuration filesType-safe configuration with validation

Migration Example

CrewAI Pattern:

research_agent = Agent(
    role='Research Specialist',
    goal='Find comprehensive information',
    backstory='Expert researcher with 10+ years experience'
)

writer_agent = Agent(
    role='Content Writer', 
    goal='Create engaging content',
    backstory='Professional writer specializing in technical content'
)

crew = Crew(
    agents=[research_agent, writer_agent],
    tasks=[research_task, write_task],
    process=Process.sequential
)

Embabel Equivalent:

@ConfigurationProperties("examples.book-writer")
record BookWriterConfig(
    LlmOptions researcherLlm,
    LlmOptions writerLlm,
    RoleGoalBackstory researcher,
    RoleGoalBackstory writer
) {}

@Agent(description = "Write a book by researching, outlining, and writing chapters")
public record BookWriter(BookWriterConfig config) {

    @Action
    ResearchReport researchTopic(BookRequest request, OperationContext context) {
        return context.ai()
            .withLlm(config.researcherLlm())
            .withPromptElements(config.researcher(), request)
            .withToolGroup(CoreToolGroups.WEB)
            .createObject("Research the topic thoroughly...", ResearchReport.class);
    }

    @Action
    BookOutline createOutline(BookRequest request, ResearchReport research, OperationContext context) {
        return context.ai()
            .withLlm(config.writerLlm())
            .withPromptElements(config.writer(), request, research)
            .createObject("Create a book outline...", BookOutline.class);
    }

    @AchievesGoal(export = @Export(remote = true))
    @Action
    Book writeBook(BookRequest request, BookOutline outline, OperationContext context) {
        // Parallel chapter writing with crew-like coordination
        var chapters = context.parallelMap(outline.chapterOutlines(), 
            config.maxConcurrency(),
            chapterOutline -> writeChapter(request, outline, chapterOutline, context));
        return new Book(request, outline.title(), chapters);
    }
}

Key Advantages:

  • Type Safety: Compile-time validation of data flow
  • Spring Integration: Leverage existing enterprise infrastructure
  • Automatic Planning: GOAP planner handles task sequencing, and is capable of more sophisticated planning
  • Tool Integration with the JVM: Native access to existing Java/Kotlin services

Migrating from Pydantic AI

Pydantic AI provides a Python framework for building AI agents with type safety and validation. Embabel offers similar capabilities in the JVM ecosystem with stronger integration into enterprise environments.

Core Concept Mapping

Pydantic AI ConceptEmbabel EquivalentNotes
@system_prompt decoratorPromptContributor classesMore flexible and composable prompt management
@tool decoratorEquivalent @Tool annotated methods can be included on agent classes and domain objectsAgent class
@Agent annotated record/classDeclarative agent definition with Spring integrationRunContext
Blackboard state, accessible via OperationContext but normally not a concern for user codeSystemPromptCustom PromptContributor
Structured prompt contribution systemdeps parameterSpring dependency injection

Migration Example

Pydantic AI Pattern:

# Based on https://ai.pydantic.dev/examples/bank-support/
from pydantic_ai import Agent, RunContext
from pydantic_ai.tools import tool

@system_prompt  
def support_prompt() -> str:
    return "You are a support agent in our bank"

@tool
async def get_customer_balance(customer_id: int, include_pending: bool = False) -> float:
    # Database lookup
    customer = find_customer(customer_id)
    return customer.balance + (customer.pending if include_pending else 0)

agent = Agent(
    'openai:gpt-4-mini',
    system_prompt=support_prompt,
    tools=[get_customer_balance],
)

result = agent.run("What's my balance?", deps={'customer_id': 123})

Embabel Equivalent:

// From embabel-agent-examples/examples-java/src/main/java/com/embabel/example/pydantic/banksupport/SupportAgent.java

record Customer(Long id, String name, float balance, float pendingAmount) {
    
    @Tool(description = "Find the balance of a customer by id")
    float balance(boolean includePending) {
        return includePending ? balance + pendingAmount : balance;
    }
}

record SupportInput(
    @JsonPropertyDescription("Customer ID") Long customerId,
    @JsonPropertyDescription("Query from the customer") String query) {
}

record SupportOutput(
    @JsonPropertyDescription("Advice returned to the customer") String advice,
    @JsonPropertyDescription("Whether to block their card or not") boolean blockCard,
    @JsonPropertyDescription("Risk level of query") int risk) {
}

@Agent(description = "Customer support agent")
record SupportAgent(CustomerRepository customerRepository) {

    @AchievesGoal(description = "Help bank customer with their query")
    @Action
    SupportOutput supportCustomer(SupportInput supportInput, OperationContext context) {
        var customer = customerRepository.findById(supportInput.customerId());
        if (customer == null) {
            return new SupportOutput("Customer not found with this id", false, 0);
        }
        return context.ai()
            .withLlm(OpenAiModels.GPT_41_MINI)
            .withToolObject(customer)
            .createObject(
                """
                You are a support agent in our bank, give the
                customer support and judge the risk level of their query.
                In some cases, you may need to block their card. In this case, explain why.
                Reply using the customer's name, "%s".
                Currencies are in $.
                
                Their query: [%s]
                """.formatted(customer.name(), supportInput.query()),
                SupportOutput.class);
    }
}

Key Advantages:

  • Enterprise Integration: Native Spring Boot integration with existing services
  • Compile-time Safety: Strong typing catches errors at build time
  • Automatic Planning: GOAP planner handles complex multi-step operations
  • JVM Ecosystem: Access to mature libraries and enterprise infrastructure

Migrating from LangGraph

LangGraph builds agent workflows using a state machine.

See the blog Build Better Agents in Java vs Python: Embabel vs LangGraph for a detailed comparison of common patterns between LangGraph and Embabel.

Migrating from Google ADK

tbd

Was this page helpful?

Share