Brief the agent like a teammate — tell it what the app tracks, who uses it, and how records move. The zango-app-developer skill handles the rest: models, roles, workflows, and AI agents, all baked in, nothing to configure.
Build a Zango app where employees submit expense reports. An AI agent reads each receipt, checks it against company policy, and flags anything over limit or missing a receipt.
Then it routes automatically — clean, small claims auto-approve; the rest go to the right manager by amount and department. Finance sees everything, and every decision is logged.
Build the Zango app described in this PRD file — models, roles, workflows, and AI agents included.
class ExpenseClaim(DynamicModelBase): employee = ZForeignKey(Employee, on_delete=models.PROTECT,tenant-aware platform field related_name="claims") department = ZForeignKey(Department, on_delete=models.SET_NULL, null=True) total_amount = models.DecimalField(max_digits=14, decimal_places=2) assigned_manager = ZForeignKey(Employee, on_delete=models.SET_NULL, null=True) # AI / rule review results ai_reviewed = models.BooleanField(default=False) ai_risk = models.CharField(max_length=10, choices=RISK_CHOICES, null=True)AI writes its verdict is_suspicious = models.BooleanField(default=False) ai_summary = models.TextField(null=True, blank=True) ai_flags = models.JSONField(default=list, blank=True)
from zango.ai.tools.decorator import ToolParam, ToolSafety, tool @tool(a tool the agent can call name="get_expense_policies", description="Return the company's active expense policies…", section="claims", safety=ToolSafety.READ_ONLY,read-only, can't mutate)def get_expense_policies() -> dict: policies = [] for p in ExpensePolicy.objects.filter(is_active=True): policies.append({"category": p.category, "per_expense_limit": float(p.per_expense_limit)}) return {"policies": policies, "count": len(policies)}
class ExpenseClaimWorkflow(WorkflowBase): status_transitions = [ {"name": "draft_to_under_review", "display_name": "Submit", "from": "draft", "to": "under_review", "roles": ["Employee", "Manager", "Finance", "Admin"]}, # … auto_approved, pending_approval, approved, paid … ] # Submit → run the AI review, then auto-route on its verdict def draft_to_under_review_done(self, request, object_instance, txn): from .ai_review import run_review decision = run_review(object_instance, actor=_actor(request))returns 'auto' or 'manager' target = ("under_review_to_auto_approved" if decision == "auto"verdict picks the path else "under_review_to_pending_approval") self.execute_transition(target, allow_system=True)