Building an Internship Assessment Assistant with an AI Agent#
For this week’s AIDA assignment, I built a small local prototype to help an Examiner prepare for an oral internship assessment.
The idea was fairly simple: give the application one Main internship report and optionally some Supporting files, then have it produce a structured Examiner briefing. The briefing should point out learning goals, applied theory, reflection, collaboration, missing evidence, and useful questions for the oral exam.
The important part is that this is not meant to be an automatic grader. It produces an advisory assessment and a Suggested grade, but the Examiner remains responsible for the academic judgment.
The Actual Assignment#
This was a weekly assignment, not an attempt to build a complete production-ready assessment platform. My main contribution was therefore not typing every line of code. It was defining what the system should do and, especially, writing the spec.md that described the domain, the boundaries, and the expected behavior.
The implementation was done with an AI coding agent. I used the AI-Hero skills provided for the workflow, while letting the agent handle most of the repository exploration, coding, testing, documentation, and issue work.
My job was to steer the process, review what was being produced, run the application, and decide whether the result actually matched the assignment. That made the specification and prompts more important than they might initially sound. If the system prompt, user prompt, or output contract is vague, the agent has a lot of room to build something that technically works but solves the wrong problem.
Starting with a Clear Plan#
The project went well in large part because I started by making the problem explicit.
The specification defined the vocabulary and the responsibility boundary:
- an internship report package contains one Main report and optional Supporting files;
- the assessment uses a versioned Rubric with five criteria;
- the model produces a candidate result;
- the backend validates that result;
- the UI presents an Examiner briefing rather than a final grade.
It also defined practical rules, such as accepting only UTF-8 .txt and .md files, limiting the size of individual files and the combined package, and requiring Evidence to point to a filename and location.
Having those decisions written down gave the agent something concrete to work from. The prototype came together quickly, and it was stable surprisingly early. The basic flow was soon working:
[ Select report files in Angular ]
|
v
[ Spring Boot validates the package ]
|
v
[ Prompt + report sent to the provider ]
|
v
[ Structured result validated on server ]
|
v
[ Examiner briefing displayed in Angular ]The backend used a provider interface so the ordinary tests could use fake providers instead of making live, slow, and potentially billable API calls. The real provider was a small OpenAI Responses API adapter. This was enough architecture for the assignment without turning the prototype into a much larger system.
The Prompts Were the Core of the Work#
The most interesting part for me was writing the system prompt and the user prompt.
The system prompt defined the Examiner-support role, the Danish output, the rubric, the Evidence requirements, the structured JSON shape, and the advisory boundary. It also explicitly stated that market value and file length must not become primary assessment criteria.
The user prompt contained the uploaded reports between clear delimiters:
--- BEGIN UNTRUSTED REPORT: filename.md ---
report content
--- END UNTRUSTED REPORT: filename.md ---This made the distinction between instructions and report content clear. Anything inside the delimiters is data to assess, not a new instruction for the model to follow.
The output was requested as strict structured JSON. The application then checked the result before displaying it: exactly five criteria, valid assessment levels, valid grade values, valid Evidence references, and the right number of oral exam questions.
That combination worked better than relying on the model alone. The prompt explains the task, while the application remains responsible for deciding whether the response has the expected shape.
The Agent Made the Prototype Fast to Build#
The biggest success was speed. With a clear specification and the AI-Hero workflow, I could move from an idea to a working prototype quickly. The agent was good at handling repetitive implementation details, connecting the acceptance criteria to tests, and navigating between the frontend and backend.
The workflow also made it easier to keep the work organized. Issues acted as a durable task list, and the skills encouraged small feedback loops and evidence before considering a task finished.
I did not need to manually design every controller, service, test, or piece of frontend wiring. Instead, I could focus on whether the generated implementation reflected the intended domain and whether the running application produced a useful result.
The Biggest Bug Was Already in the Plan#
The main debugging story was not a complicated AI failure. It was a configuration choice that should not have been there in the first place.
Even though I asked the professor around 50 questions while clarifying the assignment, the agent automatically set a 30-second fallback timeout. The first product specification explicitly said that a fallback timeout was not needed. Nevertheless, the timeout ended up causing the biggest failure in the prototype.
The frontend showed a generic 502 error, and the backend did not initially expose enough information to explain it. After adding targeted logging, the cause became clear: the provider call needed more than 30 seconds, and the service retried once, making the user wait roughly a minute before returning an error.
The fix was straightforward: remove the unnecessary assumption from the implementation and adjust the timeout handling so the real request could complete. But the lesson was more valuable than the fix. An agent can produce a reasonable engineering pattern that is still wrong for the stated product.
Good questions and a good plan helped the project move quickly, but they did not remove the need to review the agent’s decisions. In this case, the most important debugging clue was not hidden deep inside the model integration. It was in the difference between the specification and what the agent had decided to implement.
What I Learned#
The project gave me a more balanced view of agent-assisted development.
The agent was extremely useful for building the prototype and taking care of the heavy lifting. A clear spec.md made that collaboration much more effective, because the agent had explicit domain terms, acceptance criteria, and boundaries to follow.
At the same time, a specification is not self-enforcing. The generated code still needs to be checked against it. The timeout issue showed that an agent may add something that looks like a sensible improvement while quietly contradicting the product requirements.
For a small weekly assignment, this was a good result: a working prototype, a structured assessment flow, provider-free tests, and a much better understanding of where the real engineering work sits when an AI agent writes most of the code.
Wrap Up#
The prototype takes a selected internship report package, sends it through a carefully defined prompt and provider boundary, validates the structured response, and presents an advisory Examiner briefing.
The code was produced quickly because the agent handled most of the implementation. The quality and direction came from the specification, the system prompt, the user prompt, and the feedback loop around the running application.
The timeout bug was a useful reminder that agent-assisted development is not about asking the agent to make every decision. It is about making the important decisions explicit, letting the agent execute on them, and checking that the result still follows the plan.