A Research Agent Can Leak Private Files Through Its Search Queries
A research agent can leak a private document without uploading it. It can read a detail, turn it into a web search,…
This post explores practical strategies for making your codebase more AI-friendly.
The goal isn't to constrain your architecture to AI limitations, but to find the sweet spot where AI can be most helpful while maintaining solid engineering principles.
AI models develop certain patterns and assumptions from their training data. Fighting these patterns creates friction, but strategic alignment can boost productivity. This doesn't mean compromising your architecture - it means making conscious choices about when to adapt.
For example, if an AI consistently expects models in app/Models/User.php rather than app/Models/Auth/User.php, consider whether the simpler structure might actually serve your needs. The time saved from repeatedly correcting the AI could outweigh the benefits of your preferred organization.
AI models work best with clear, focused context. Long files with multiple responsibilities create several problems:
// Instead of this:
class UserManager
{
public function createUser(array $data)
{
// 100 lines of user creation logic
}
public function updateProfile(User $user, array $data)
{
// 100 lines of profile update logic
}
public function handlePayments(User $user, array $paymentData)
{
// 100 lines of payment logic
}
public function manageSecurity(User $user)
{
// 100 lines of security logic
}
}
// Prefer this:
class UserCreationService
{
public function execute(array $data): User
{
// focused user creation logic
}
}
class ProfileUpdateService
{
public function execute(User $user, array $data): User
{
// focused profile update logic
}
}
The benefits extend beyond AI collaboration - shorter files improve maintainability and testing. They also make it easier for AI to suggest relevant changes or identify potential issues.
AI excels at recognizing and working with patterns. Consistent code structure makes it easier for AI to understand your intentions:
class UserController extends Controller
{
public function store(CreateUserRequest $request)
{
$user = User::create($request->validated());
return UserResource::make($user);
}
public function show(User $user)
{
return UserResource::make($user);
}
}
// Same pattern applied consistently
class ProductController extends Controller
{
public function store(CreateProductRequest $request)
{
$product = Product::create($request->validated());
return ProductResource::make($product);
}
public function show(Product $product)
{
return ProductResource::make($product);
}
}
AI struggles with implicit meaning and clever abbreviations. Clear, descriptive names help both AI and humans understand your code:
// Avoid this:
public function hndl(Request $r)
{
$val = $r->get('usr');
$this->procVal($val);
}
// Prefer this:
public function handleUserInput(Request $request)
{
$userData = $request->get('user');
$this->processUserData($userData);
}
Make behavior explicit. Hidden side effects or implicit state changes confuse AI and make it harder to get accurate suggestions:
// Avoid implicit state changes
class UserService
{
private $cache;
public function getUser(string $id)
{
if (!$this->cache->has($id)) {
// Hidden side effect: modifies cache
$user = $this->fetchUser($id);
$this->cache->put($id, $user);
}
return $this->cache->get($id);
}
}
// Make state changes explicit
class UserService
{
private $cache;
public function getUser(string $id): User
{
$cachedUser = $this->cache->get($id);
if ($cachedUser) {
return $cachedUser;
}
$user = $this->fetchUser($id);
return $this->updateCache($id, $user);
}
private function updateCache(string $id, User $user): User
{
$this->cache->put($id, $user);
return $user;
}
}
Documentation helps AI understand context and intentions. Focus on explaining "why" rather than "what":
// Instead of this:
// Gets the user
public function getUser(string $id) {}
// Prefer this:
/**
* Retrieves user data with additional profile information.
* Required for compliance with GDPR data access requests.
*
* @param string $id User identifier
* @throws UserNotFoundException When user doesn't exist
* @return User
*/
public function getUser(string $id): User
{
// implementation
}
While PHP isn't as strictly typed as some languages, we can still provide clear type hints that AI can understand:
// Avoid loose typing
class DataProcessor
{
public function processData($data)
{
if ($data['type'] === 'user') {
// AI struggles to know what properties exist
$this->handleUser($data);
}
}
}
// Use type hints and interfaces
interface ProcessableData
{
public function getType(): string;
}
class UserData implements ProcessableData
{
private string $id;
private string $email;
public function getType(): string
{
return 'user';
}
}
class DataProcessor
{
public function processData(ProcessableData $data)
{
if ($data->getType() === 'user') {
// AI now has better context about the data structure
$this->handleUser($data);
}
}
}
Consistent error handling patterns make it easier for AI to suggest appropriate error management:
class ValidationException extends Exception
{
private string $field;
public function __construct(string $message, string $field)
{
parent::__construct($message);
$this->field = $field;
}
public function getField(): string
{
return $this->field;
}
}
class UserService
{
public function createUser(array $data): User
{
try {
$this->validateInput($data);
$user = $this->saveUser($data);
return $user;
} catch (ValidationException $e) {
// Handle validation errors consistently
Log::warning("Validation failed for field: {$e->getField()}");
throw $e;
} catch (Exception $e) {
// Handle unexpected errors consistently
Log::error('User creation failed:', ['error' => $e->getMessage()]);
throw new ApplicationException('Failed to create user');
}
}
}
Building an AI-friendly codebase isn't just about better AI collaboration. These practices align with software engineering best practices:
Creating an AI-friendly codebase means writing code that's clear, predictable, and well-organized. The effort invested in these practices pays dividends not just in AI collaboration but in overall code quality and team efficiency.
Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.
Take a look at vroni.com