Universal Transformation Framework: Building Cross-Framework AI Agents
Universal Transformation Framework: Building Cross-Framework AI Agents
The AI ecosystem is evolving rapidly, with new frameworks and models emerging constantly. For developers building LLM-powered applications, this presents a challenge: how do you build applications that aren’t tied to a specific framework or vendor? At knify, we’ve developed a Universal Transformation Framework that addresses this challenge head-on, allowing you to define AI agents once and deploy them across multiple frameworks.
The Multi-Framework Challenge
If you’ve worked with LLMs in production, you’ve likely encountered these challenges:
- You start with one framework (like LangChain) but later need features from another
- A new model or service emerges that requires a different framework
- Different parts of your stack use different languages (Python, TypeScript, Go)
- Costs or performance lead you to switch providers
Traditionally, these transitions require significant rewrites, sometimes from scratch. Our Universal Transformation Framework offers a better way.
The Universal Agent Specification
At the core of our approach is a framework-agnostic specification for AI agents. Here’s a simplified example:
// A universal agent specification in Go
type UniversalAgentSpec struct {
Name string
Model string
SystemPrompt string
Query string
Temperature float64
}
// Example agent definition
myAgent := UniversalAgentSpec{
Name: "CustomerSupportAgent",
Model: "gpt-4",
SystemPrompt: "You are a helpful customer support agent for a software company.",
Query: "How can I help you today?",
Temperature: 0.7,
}
This specification is deliberately simple and focuses on the core attributes that define an agent’s behavior rather than the implementation details of how it runs.
Transforming Across Frameworks and Languages
The magic happens in the transformation layer. Using AST (Abstract Syntax Tree) parsing and code generation techniques, our framework can:
- Parse a universal specification from source code
- Transform it into code for different target frameworks
- Generate implementations in different programming languages
For example, our transformation engine can turn the Go specification above into Python code for LangChain:
# Generated Python code for LangChain
from langchain.chat_models import ChatOpenAI
from langchain.schema import SystemMessage, HumanMessage
chat = ChatOpenAI(
model_name="gpt-4",
temperature=0.7
)
system_message = SystemMessage(content="You are a helpful customer support agent for a software company.")
human_message = HumanMessage(content="How can I help you today?")
response = chat([system_message, human_message])
Or into TypeScript code for another framework:
// Generated TypeScript code for another framework
import { Agent } from "some-other-framework";
const agent = new Agent({
name: "CustomerSupportAgent",
model: "gpt-4",
systemPrompt:
"You are a helpful customer support agent for a software company.",
initialMessage: "How can I help you today?",
settings: {
temperature: 0.7,
},
});
How It Works: AST Parsing and Code Generation
Under the hood, our transformation engine uses several powerful techniques:
1. AST Parsing to Extract Specifications
We use language-specific Abstract Syntax Tree (AST) parsers to read source code and extract the universal specifications. For example, in Go:
func parseAgentSpecFromGoFile(filename string) (UniversalAgentSpec, error) {
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
if err != nil {
return UniversalAgentSpec{}, err
}
var spec UniversalAgentSpec
ast.Inspect(node, func(n ast.Node) bool {
// Logic to identify and extract UniversalAgentSpec from the AST
// ...
return true
})
return spec, nil
}
2. Templating for Code Generation
We use template engines to generate code for target frameworks:
func generatePydanticCode(spec UniversalAgentSpec) (string, error) {
const tmpl = `
from pydantic import BaseModel
from typing import Optional
class {{.Name}}(BaseModel):
model: str = "{{.Model}}"
system_prompt: str = """{{.SystemPrompt}}"""
temperature: float = {{.Temperature}}
def run(self, query: str = "{{.Query}}"):
# Implementation details...
pass
`
// Use template engine to render the code
// ...
}
3. Framework-Specific Adapters
Each target framework has an adapter that handles its specific requirements and best practices:
type FrameworkAdapter interface {
GenerateCode(spec UniversalAgentSpec) (string, error)
ValidateSpec(spec UniversalAgentSpec) error
}
type LangChainAdapter struct{}
type PydanticAdapter struct{}
// ...
Practical Applications in knify
In the knify ecosystem, the Universal Transformation Framework enables several powerful capabilities:
Framework Migration
When you need to move from one framework to another:
$ knify transform agent.go --from go --to python --framework langchain
Multi-Framework Deployment
Deploy the same agent definition to multiple frameworks simultaneously:
# In knify's Python API
agent_spec = load_universal_spec("agent.go")
langchain_agent = transform_to_langchain(agent_spec)
llama_index_agent = transform_to_llama_index(agent_spec)
Cross-Language Teams
Enable collaboration between teams using different languages:
# Python team defines agent:
customer_agent.py → universal_spec → typescript_agent.ts
# TypeScript team can use it directly
Beyond Simple Agents: Handling Complex Behavior
The examples so far have been simple, but our framework scales to complex agent behaviors:
- Tool/Function Calling: Universal specifications for tools and function calling
- Memory and State: Framework-agnostic definitions for memory systems
- Custom Workflows: Specifications for multi-step agent interactions
type UniversalTool struct {
Name string
Description string
Parameters []ToolParameter
Handler string // References function name in host language
}
type UniversalMemory struct {
Type string // "buffer", "summary", "vector", etc.
Capacity int
Persistence string // "session", "user", "global"
}
Try It Today
The Universal Transformation Framework is available as part of the knify toolkit. To get started:
- Define your agents using our universal specification
- Use our CLI tools or APIs to transform them
- Deploy across frameworks without rewriting your core logic
In our next article, we’ll dive into PML (Python Markup Language) and how it’s enhancing the Python development experience with advanced compiler and highlighter systems.
Stay tuned for more insights into how knify is reshaping modern web development!