PART 1 -
AI is probably coming for all of us eventually. It promises to make companies “more efficient” but how far along is it right now? Can it really be used to replace software developers? Can you just pick a tech stack, tell AI what to write and put your feet up while the money rolls in?
Using these plug-ins requires an API key but acquiring one is not as straightforward as you might expect. You create your account and login at and there is no obvious link… or at least there was none during my initial draft but now there is. :)
Once I had my API key, I needed to add credits to my account or API requests would be rejected. Luckily, Anthropic is running a $5 credit promotion which appears in your dashboard. I accepted the offer, was texted a validation code which I entered and then…nothing. I did not see any credits. I was stuck in a loop of offer/validation/acceptance and could not get the credits to appear in my account. I sent them an email and figured I would try again the next day.
The next day came and there was no reply so I just decided to purchase $5 worth of credits and get on with the show. First up, I would try Aider which runs in a VS Code terminal window. I am not crazy about the UI but configuration was easy enough, it makes Github commits after each step and it gets great reviews on Youtube so it was worth a try.
Here is the initial prompt I used. I chopped it into a couple of pieces so I could check the work as we went along. Much like people, AI works best iteratively, giving you a chance to make sure things are working as intended at each milestone and giving you an opportunity to debug and clean up.
[START FIRST PROMPT]
I would like to create simple help desk software using AI to build the product. Instructions will be given iteratively so it can be built piece by piece.
You are an expert web developer with expertise in Python and Flask. All code must be secure to prevent SQL injection and other attacks. All fields must have reasonable size limits and maxlengths. Field lengths and data types are to be protected on the client and server side.
The technical requirements are:
Python
Flask
Fast-API
Bootstrap
jQuery
We will initially use SQLite for simplicity but will move to MySQL at some point so keep that in mind.
All pages must be responsive and work well on desktop, tablet and mobile screen resolutions. The product will be API-First with all CRUD operations working through the API layer using Fast-API. This includes fields for support tickets as well as administration such as users, preferences and other settings.
Integrations with other popular products such as Slack, JIRA and Salesforce and the ability to send data to a webhook URL will be important for adoption so keep that in mind while building the core of this platform.
[END FIRST PROMPT]
[START SECOND PROMPT]
Product requirements for the first iteration:
Build a lefthand bar with the following links:
Tickets
Integrations
Workflows
Team
Settings
Each of these links will be its own files in the templates directory.
When clicking one of the entries on the left navigation bar, the right side will refresh with the necessary data. Examples:
When you click Tickets, show a list of existing cases and a link to create a new case.
When creating a new case, display the following fields:
Ticket ID (Numeric, auto generated, read only but visible)
Customer First Name (field length 25, maxlength 50)
Customer Last Name (field length 25, maxlength 50)
Customer Email (field length 25, maxlength 50)
Subject (field length 50, maxlength 100)
Priority (Dropdown with values 1-Urgent, 2-Important, 3-Normal, 4-Low)
Assignee (Dropdown with a list of dummy data for now)
Details (Large textarea, maxlength 50,000)
There should be a save button so you can save the case.
When you click Integrations on the left navigation bar, show logos and placeholder data for Slack, JIRA and Salesforce.
When you click Workflows on the left navigation bar, show a placeholder header graphic and placeholder data.
When you click Team on the left navigation bar, show a placeholder header graphic and placeholder data.
When you click Settings on the left navigation bar, show a placeholder header graphic and placeholder data.
[END SECOND PROMPT]
After running the first part of the prompt, I checked the project structure and files. I was surprised and impressed to find that it generated a modular Flask file structure, with blueprints, separate routes files and Pydantic for strong typing which I believe is required for FastAPI.
I spent some more time on the server restart problem the next day but still had no luck so I decided to add this requirement to the project requirement prompts along with some other tweaks to fix shortcomings from the first round. I created a new folder and went another round with Aider:
[START FIRST PROMPT]
I would like to create simple help desk software using AI to build the product. Instructions will be given iteratively so it can be built piece by piece.
You are an expert web developer with expertise in Python and Flask. All code must be secure to prevent SQL injection and other attacks. All fields must have reasonable size limits and maxlengths. Field lengths and data types are to be protected on the client and server side.
The technical requirements are:
Python
Flask
Fast-API
Bootstrap
jQuery
We will initially use SQLite for simplicity but will move to MySQL at some point so keep that in mind.
I am using VS Code as my IDE. Please make sure that changes to all files such as HTML templates and CSS files trigger an automatic restart of the web server.
All pages must be responsive and work well on desktop, tablet and mobile screen resolutions. The product will be API-First with all CRUD operations working through the API layer using Fast-API. This includes fields for support tickets as well as administration such as users, preferences and other settings.
Integrations with other popular products such as Slack, JIRA and Salesforce and the ability to send data to a webhook URL will be important for adoption so keep that in mind while building the core of this platform.
Let me know how to install all the necessary dependencies.
[END FIRST PROMPT]
[START SECOND PROMPT]
Product requirements for the first iteration:
Build a lefthand bar with the following links:
Tickets
Integrations
Workflows
Team
Settings
Each of these links will be its own files in the templates directory.
When clicking one of the entries on the left navigation bar, the right side will refresh with the necessary data and the left navigation bar will still appear. Examples:
When you click Tickets, show a list of existing cases and a link to create a new case.
When creating a new case, display typical fields that are found in ticketing software. Each should have a reasonable field length and maxlength.
There should be a save button so you can save the case to the database.
When you click Integrations on the left navigation bar, show logos and placeholder data for Slack, JIRA and Salesforce.
When you click Workflows on the left navigation bar, show a placeholder header graphic and placeholder data.
When you click Team on the left navigation bar, show a placeholder header graphic and placeholder data.
When you click Settings on the left navigation bar, show a placeholder header graphic and placeholder data.
[END SECOND PROMPT]
I ended up with a similar file structure as the first attempt but the server would not start due to circular import issues, a familiar pain point for Python developers when they try to modularize their code and break pieces into separate directories:
ImportError: cannot import name 'routes' from partially initialized module 'helpdesk_app' (most likely due to a circular import) (/home/joe/Documents/programming/python/helpdesk2/helpdesk_app/__init__.py)
Aider was able to fix this and similar issues after several attempts. Finally, I could get the server to start without issue but when I tried to hit the homepage, it generated a database exception which I fed back to Aider:
When I try to hit the homepage I am getting this error. It looks like a problem with the database: sqlite3.OperationalError: no such table: tickets
Aider itself immediately crashes with:
Traceback (most recent call last):
File "/home/joe/Documents/programming/python/helpdesk1/.venv/bin/aider", line 8, in <module>
sys.exit(main())
^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/main.py", line 620, in main
coder.run()
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 685, in run
self.run_one(user_message, preproc)
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 723, in run_one
list(self.send_message(message))
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 945, in send_message
messages = self.format_messages()
^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 904, in format_messages
messages_tokens = self.main_model.token_count(messages)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/models.py", line 532, in token_count
return litellm.token_counter(model=self.name, messages=messages)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/litellm/utils.py", line 1987, in token_counter
num_tokens += calculage_img_tokens(
^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/litellm/utils.py", line 1834, in calculage_img_tokens
resized_width, resized_height = resize_image_high_res(
^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/litellm/utils.py", line 1751, in resize_image_high_res
if width <= 768 and height <= 768:
^^^^^^^^^^^^
TypeError: '<=' not supported between instances of 'NoneType' and 'int'
(.venv) joe@mint:~/Documents/programming/python/helpdesk1$ aider
Aider v0.49.1
Models: claude-3-5-sonnet-20240620 with diff edit format, weak model claude-3-haiku-20240307
Git repo: .git with 21 files
Repo-map: using 1024 tokens
VSCode terminal detected, pretty output has been disabled.
Trying again:
It looks like the database tables were never created or initialized. Can you create code to do so?
Traceback (most recent call last):
File "/home/joe/Documents/programming/python/helpdesk1/.venv/bin/aider", line 8, in <module>
sys.exit(main())
^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/main.py", line 620, in main
coder.run()
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 685, in run
self.run_one(user_message, preproc)
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 723, in run_one
list(self.send_message(message))
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 945, in send_message
messages = self.format_messages()
^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 892, in format_messages
messages += self.get_files_messages()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 592, in get_files_messages
repo_content = self.get_repo_map()
^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/coders/base_coder.py", line 564, in get_repo_map
repo_content = self.repo_map.get_repo_map(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/repomap.py", line 105, in get_repo_map
files_listing = self.get_ranked_tags_map(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/repomap.py", line 448, in get_ranked_tags_map
num_tokens = self.token_count(tree)
^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/repomap.py", line 69, in token_count
return self.main_model.token_count(text)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/models.py", line 542, in token_count
return len(self.tokenizer(msgs))
^^^^^^^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/models.py", line 528, in tokenizer
return litellm.encode(model=self.name, text=text)
^^^^^^^^^^^^^^
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/llm.py", line 20, in __getattr__
self._load_litellm()
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/aider/llm.py", line 27, in _load_litellm
self._lazy_module = importlib.import_module("litellm")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/importlib/__init__.py", line 90, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 995, in exec_module
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/litellm/__init__.py", line 20, in <module>
from litellm.proxy._types import (
File "/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/litellm/proxy/_types.py", line 10, in <module>
from pydantic import BaseModel, ConfigDict, Extra, Field, Json, model_validator
ImportError: cannot import name 'model_validator' from 'pydantic' (/home/joe/Documents/programming/python/helpdesk1/.venv/lib/python3.12/site-packages/pydantic/__init__.py). Did you mean: 'root_validator'?
Another exception - something Pydantic related? Way out of my league...
Everything seemed to work OK and I was also impressed with what Claude did with the skeleton of the Integrations page:
I noticed that the .gitignore file was generated but it was not excluding the “.venv” directory which was my mistake. I originally instructed it to look for a “venv” directory instead of a “.venv” directory. AI is only as smart as what you feed it and it can’t read your mind. Yet.
I then prompted:
The basic frameworks seems to be working OK but I would like to add more fields for each ticket. Please add more field types that would be typical of a helpdesk ticketing application. Each field must be an appropriate length with maxsize enforced on the client and server side.
Also create the ability to edit each ticket from the tickets page. Clicking the ticket ID field would be the logical place to add this functionality.
This worked great and I thanked Claude and prompted him to take a break but I got this error message:
429 {"type":"error","error":{"type":"rate_limit_error","message":"Number of request tokens has exceeded your per-minute rate limit (https://docs.anthropic.com/en/api/rate-limits); see the response headers for current usage. Please reduce the prompt length or the maximum tokens requested, or try again later. You may also contact sales at https://www.anthropic.com/contact-sales to discuss your options for a rate limit increase."}}
OK then… I let it sit for a while and wanted to see if Claude could add “ticket delete” functionality. I created a new branch and prompted:
Please now add the ability to delete a ticket. For now, let’s just mark a ticket as deleted and not physically delete it from the database. Add a delete option to each ticket in the listing of all tickets. Use an X icon. Confirm deletion. Hide deleted tickets from the list of all tickets. We will soon build a view to show only deleted tickets. Be sure to update the database schemas as appropriate.
This returned another rate limit error:
429 {"type":"error","error":{"type":"rate_limit_error","message":"Number of request tokens has exceeded your daily rate limit (https://docs.anthropic.com/en/api/rate-limits); see the response headers for current usage. Please reduce the prompt length or the maximum tokens requested, or try again later. You may also contact sales at https://www.anthropic.com/contact-sales to discuss your options for a rate limit increase."}}
Womp, womp… I guess Claude will get the rest of the day off and I will see how far I can push it tomorrow.
The next day, I fed the same prompt and it returned a well thought out response to show that it understood the technical requirements:
To accomplish this task, we'll need to make several changes to our existing codebase. Let's break it down into steps and use the available tools to implement these changes.
We need to update the database schema to add a 'deleted' column to the tickets table.
We need to modify the app.py file to add a new route for deleting tickets.
We need to update the tickets.html template to add a delete button with an X icon for each ticket.
We need to modify the existing route that lists all tickets to exclude deleted tickets.
Let's start by examining the current state of our app.py file and the tickets.html template.
After showing me the proposed change step-by-step, Claude reported back that it was done!
Task Completed
The ability to delete tickets has been successfully implemented. Here's a summary of the changes:
Updated the Ticket model in app.py to include a 'deleted' column (Boolean, default False).
Modified the tickets route to only show non-deleted tickets using Ticket.query.filter_by(deleted=False).all().
Added a new route /tickets/<int:id>/delete for soft deleting tickets.
Updated the tickets.html template to include a delete button with an X icon for each ticket.
Added confirmation dialog before deleting a ticket.
Ran database migrations to apply the schema changes.
These changes allow users to mark tickets as deleted without physically removing them from the database. Deleted tickets are hidden from the main ticket list, and we can easily implement a view to show only deleted tickets in the future.
To see the changes in action, you can run the Flask application and navigate to the tickets page. You should see the new delete buttons (X icons) next to each ticket. Clicking on a delete button will prompt for confirmation before marking the ticket as deleted.
I saw the new column in the database but now none of my tickets were appearing in the list:
I am not too crazy about the delete icon but I am just about out of Claude credits. I will continue on this journey for the next part of this journal.
SIDE NOTE - While iterating on this project, I somehow ended up with an instance that requires user login for all of the pages. I did not explicitly ask for this and I am not sure how we ended up here. I had to reboot my system and lost all my Aider / Claude history and I am not sure if it can be retrieved. However, the first check in for the Master branch does show a “flask_login” import, followed by a bunch of fixes and refactors. Those refactors added a @login_required decorator to every page.
After all those fixes and refactors, each page of the UI is asking for a login but there is no mechanism for creating an account. I will need this feature at some point but not yet. Now it is just in the way. This goes to show that you should not blindly accept the code without reviewing it and you really need to understand what you are looking at. Claude took creative liberties and added a feature I did not ask for.
This was an interesting exercise for me and hopefully you found it insightful. I found that Claude has the same battles I would have once I push beyond a basic Flask setup - issues with circular imports, dependency version hell, etc. New day, new tool, same old problems.
Just like any of the “no code tools”, the audience that will benefit the most are the people who have had experience writing code from line one, understand programming concepts, are able to clearly explain requirements in the written form and have troubleshooting experience in the tech stack at hand.
I will be pushing this project further iteratively to see how far I can take it.
Next up: Integrations!
About the Author
Joe Giglio is a 25+ year veteran of the software industry. In his career, he has worked for a local dial-up ISP, startups of all sizes and a well established, slow moving enterprise. There were important lessons learned along every stop.
His recent projects include:
Remote work training and consulting:
Remote company rankings. Think "Glassdoor for remote companies": |
↗ Original-Artikel auf dev.to lesenVollständiger Original-BerichtAusführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
SOCIAL SHARE CARD GENERATOR