Skip to main content

14 posts tagged with "architecture"

View All Tags

Lightweight Skills, Strong Tools: A Practical Architecture for Reliable AI Agents

· 9 min read
Philip Z
Architect

As AI agents become more capable, it is tempting to make their Skills increasingly detailed. Every new failure becomes another instruction. Every exception becomes another paragraph. Eventually, the Skill tries to describe the domain, encode the workflow, enforce safety, teach the tool interface, and anticipate every future mistake.

That approach does not scale.

Our practical conclusion is different:

Keep Skills lightweight. Make Tools strong.

This is not an argument for fewer safeguards. It is an argument about where safeguards belong.

It is also a principle for harness engineering. The core of an agent harness should not be an ever-growing library of Skills. It should be a set of strong, model-aware Tools and deterministic feedback loops that turn guidance into enforceable action boundaries.

Dynamic World Models: The Missing Requirements Layer for AI-Native Software Engineering

· 11 min read
Philip Z
Architect
Clariones Wang
Jacky Tian

AI can generate code. That does not mean it understands the world the code is supposed to represent.

This distinction is becoming one of the central problems in AI-native software engineering. A model may produce a plausible database schema, API, or workflow while missing an implicit business rule, confusing a role with a person, or treating a derived state as a source of truth. The output can be syntactically correct and still describe the wrong system.

The missing layer is not another code generator. It is a better representation of requirements.

We call this representation a Dynamic World Model: a reasoning framework for explaining how a domain works and why it is in its current state. In this framework, concepts participate in events, under constraints, to create and evolve relationships. Software is then generated or implemented as an executable projection of that explanation.

Numeric Entity IDs Across Rust, Java, Go, Python, SQL, and JSON

· 6 min read
TeaQL Team
Core Team

An entity ID looks like a small implementation detail until the same value has to survive a database join, a Rust service, a Java service, a Go worker, a Python script, and a browser. Each environment can represent a different set of integers, and accepting the widest type in one layer can make the whole system less portable.

TeaQL therefore separates three decisions:

  • persistence identities and foreign keys are compact numeric values;
  • their portable persisted range is the positive signed 64-bit range;
  • IDs crossing a JSON boundary are encoded as decimal strings.

The range is enormous for an identity space, but small enough to have a direct, unambiguous representation in the database and in the major server languages TeaQL supports.

Removing Reflection from TeaQL Java's Core Path: Runtime Determinism as Harness Engineering

· 12 min read
Philip Z
Architect

TeaQL Java did not remove every use of reflection from the repository. We did something more practical: we removed reflection from the core entity execution path, isolated the remaining reflective utilities, and added build-time guardrails to stop reflection from quietly returning.

GraalVM Native Image was an important forcing function, but it was not the highest-level reason for the work. The larger goal was to make the runtime environment more deterministic: important behavior should be explicit, inspectable, bounded, and enforceable before a production request reaches it.

We see that as harness engineering. The reliability of a system should not depend only on developers or coding agents remembering the right conventions. The surrounding environment—generated code, metadata, module boundaries, compiler-visible calls, build rules, and tests—should constrain execution into known-good paths.

TeaQL Java Runtime: Modular Refactor, Multi-Framework Ready, Rust-Aligned

· 6 min read
Philip Z
Architect

We refactored the TeaQL Java runtime (teaql-java) to achieve three goals:

  1. JPMS module boundaries — seal internal packages, expose only what generated code needs
  2. Spring Boot independence — run without Spring Boot using a plain main() function
  3. Rust alignment — dual-layer audit logging, compile-time query enforcement, RequestPolicy

Declarative Data Service Routing for Polyglot Persistence

· 4 min read
TeaQL Team
Core Team

In modern complex application architectures, polyglot persistence has almost become a standard configuration. Within a single system, core transactional data may require PostgreSQL for strong consistency guarantees, massive execution logs might need Meilisearch for full-text search, state information could be thrown into Redis for ultra-high-speed caching, and local development might even downgrade to rusqlite.

The trade-off is coordination complexity: connection pools, provider SDKs, and routing decisions can leak into application code.

Kernel-Level Audit & Privacy: Building Resilient Audit Chains in the AI Coding Era

· 6 min read
Philip Z
Architect

In the era of AI Coding, business code may be co-generated and modified by human developers, AI agents, or automated tools. This brings a new challenge:

While business logic is becoming increasingly easy to generate automatically, the audit chain must not become fragile as a result.

Traditional audit systems often rely on business code to actively record logs. However, in AI Coding scenarios, this approach carries clear risks:

  • AI might forget to write audit logs;
  • AI might accidentally disable logs;
  • AI might generate code that bypasses audits;
  • Business code might unintentionally record sensitive plain text;
  • A custom audit hook might access raw data it shouldn't see;
  • Long strings, JSON payloads, or execution logs might cause audit log bloating or even out-of-memory (OOM) errors.

Therefore, TeaQL underwent a low-level refactoring to move auditing capabilities into the framework kernel rather than leaving them entirely to the business code. We established the following core principles:

Audit must be kernel-level.
Business code may enrich audit trails, but it cannot erase them.
Sensitive fields do not disappear; only their plain text disappears.

The Return of E Expressions: Fluent Chaining and Structured Panics for AI Auto-Healing

· 4 min read
Philip Z
Architect

In the evolution of TeaQL, we've constantly navigated the tension between developer ergonomics and idiomatic Rust. We recently brought the E:: fluent expression chain back to Rust.

This is not a simple rollback. The new design uses reference chaining instead of cloning entity graphs and emits structured diagnostics when a relation was not loaded.

Why AI-generated software needs deterministic business APIs

· 2 min read
TeaQL Team
Core Team

AI coding tools can produce useful application code quickly. The problem is not speed. The problem is boundary control.

If an AI tool has to infer persistence behavior from scattered SQL, repositories, mapper XML, DTOs, and service conventions, it will eventually guess wrong.

TeaQL exists to make that boundary deterministic.

The Guessing Problem

When AI writes data-access code directly, it must infer:

  • table names;
  • column names;
  • relation cardinality;
  • tenant filters;
  • permission rules;
  • deleted-row semantics;
  • transaction boundaries;
  • pagination rules;
  • response shape;
  • database dialect differences.

Some of these guesses can pass a simple test and still be wrong in production.

The Business API Boundary

TeaQL generates APIs from the domain model. That means AI code can compose with named business methods instead of inventing storage behavior.

let orders = Q::orders().select_customer_with(Q::customers().comment("Query customers").purpose("Load data").select_name())
.select_line_item_list_with(Q::line_items().comment("Query line_items").purpose("Load data").select_sku())
.which_statuses_are("PAID")
.page(1, 20)
.comment("Query orders").purpose("Load data")
.execute_for_list(&ctx)
.await?;

The model controls what fields and relations exist. The runtime controls how the query executes. The AI composes within those boundaries.

Deterministic Does Not Mean Rigid

A deterministic API can still be expressive:

  • filters can be combined;
  • relation loads can be nested;
  • aggregates can be grouped;
  • graph writes can save parent and child objects together;
  • provider-specific behavior can be selected below the API.

The point is that the API surface is stable and reviewable.

Better Prompts

TeaQL also makes prompts smaller.

Instead of giving an AI tool the entire schema, SQL examples, repository conventions, and DTO rules, a team can provide a generated API guide:

Use TeaQL Q APIs for reads.
Use generated relation selectors.
Execute through UserContext.
Do not write raw SQL unless explicitly requested.
Use graph save for parent-child persistence.

That is a stronger contract than a long explanation of database structure.

Runtime Safety

The generated API is only half the story. Runtime boundaries matter too.

TeaQL keeps execution behind context and provider layers:

  • Java uses UserContext as the runtime boundary.
  • Rust uses teaql_runtime::UserContext, repository registries, behavior hooks, and provider registration.
  • Database providers execute against PostgreSQL, MySQL, SQLite, rusqlite, or memory.

AI-generated application code should not own those decisions.

The Short Version

AI tools are fast at composition. They are unreliable at reconstructing business rules from infrastructure code.

TeaQL gives them deterministic business APIs to compose.

Core Architecture Refactor: Modularization and Reactive Support

· One min read
TeaQL Team
Core Team

TeaQL core was decoupled from Spring, the SQL repository became its own module, and WebFlux reactive support was added.

Module Split

Before

teaql (monolithic)
├── Entity/Request/Context
├── SQLRepository (all databases)
└── Spring auto-config

After

teaql (core, no Spring dependency)
├── Entity/Request/Context
├── Expression framework
└── Checker

teaql-sql (SQL repository base)
teaql-mysql / teaql-pg / teaql-oracle (database-specific)
teaql-autoconfigure (Spring Boot starter)

WebFlux Support

+ WebFlux reactive endpoint support
- Removed spring-boot-starter-web dependency from core

TeaQL now works with both Spring MVC and Spring WebFlux.

JDBC DataSource

Added JdbcDataSource for explicit JDBC connection management.

TeaQL is Born: Type-Safe Query Expressions

· One min read

This is where TeaQL began. In November 2022, the core runtime shipped with 95 files and 4,636 lines of code.

Core Capabilities

SQL Expression Parser

SQLExpressionParser, PropertyParser, and RawSqlParser form the foundation of type-safe query expressions:

Q.orders().filter(
Q.orders().comment("Query orders").purpose("Load data").customer().city().eq("Shanghai")
).comment("Query orders").purpose("Load data").executeForList(ctx);

Sub-Query Support

SubQueryParser (62 lines) enables nested queries expressed naturally in Java:

Q.orders().filter(
Q.orders().comment("Query orders").purpose("Load data").customer().city().eq("Shanghai")
).comment("Query orders").purpose("Load data").executeForList(ctx);

Dynamic Aggregation Framework

SimpleAggregation supports count, sum, avg, and more directly from the domain model.

Architecture at a Glance

  • Expression-based queries: Type-safe Java expressions compiled to SQL
  • Repository pattern: SQLRepository as the base with database-specific extensions
  • Sub-query composition: Nest queries naturally in Java
  • Aggregation framework: First-class aggregate function support

These patterns remain the foundation of TeaQL today.