All jobs

Answer Support Tickets from a Rails Codebase

Yes. Your backend sends each ticket to the API, an agent finds the rule in your Rails models, and the reply comes back as JSON on your webhook.

Run this on RushIn a Project that has your repository.

What the agent does

A ticket arrives in your help desk and your backend starts one run for it, with the app's repository in resources and the customer's question in the prompt. The agent clones the repository into its own cloud sandbox and answers from code. In a Rails app like lobsters/lobsters, it sees Rails 8.1 in Gemfile.lock, Ruby 4.0 from .ruby-version, and the posting rules as validations on Story in app/models/story.rb, with the domain record in app/models/domain.rb.

For "why can a new account not post links to some domains?", the agent starts at what "new" means. User#is_new? in app/models/user.rb is true while created_at is within NEW_USER_DAYS, which the same file sets to 70. Then it reads the validations that call it. check_not_new_domain_from_new_user adds "is an unseen domain from a new user." when a new user submits a URL whose domain has no stories that are not deleted, and opens a mod mail to the user's inviter explaining the rule.

It reads the neighbouring rules, because a customer's link may fail for a different reason that looks the same. check_not_banned_domain refuses any user's link to a domain with banned_at set and quotes banned_reason; check_not_banned_origin does the same for an origin. check_not_brigading stops new users from linking into project bug trackers and discussions on GitHub, GitLab, Codeberg and others. check_tags stops new users from using tags where permit_by_new_users is false. Each has its own error text, so the reply can tell the customer which one they hit.

The agent writes the JSON the prompt asks for: two short paragraphs a member of the community can read, the files and lines for each rule, and its confidence. It changes no code. The answer says when the rule stops applying, 70 days after signup, and that a link to a domain someone has already posted is not refused by this rule.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "A customer asks: why can a new account not post links to some domains? Find the answer in this repository's code, not its docs: read User#is_new? and NEW_USER_DAYS in app/models/user.rb, then every Story validation in app/models/story.rb that refuses a URL, and the Domain model. Say which rule matches each error message and when it stops applying. Reply with JSON: answer (two short paragraphs a customer can read), files (paths and lines that prove it), and confidence. Do not change code.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
  1. Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
  2. Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
  3. Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

What comes back

The run's final answer is the JSON object the prompt asks for. answer explains that accounts younger than 70 days cannot submit a link to a domain nobody has posted before, and how that differs from a banned domain, which no account can post. files cites app/models/user.rb for is_new? and NEW_USER_DAYS, and app/models/story.rb for check_not_new_domain_from_new_user and check_not_banned_domain, with lines. confidence reflects whether the customer's error text was in the ticket.

It reaches your backend as data.result on the run.completed webhook, and the session read returns the same result. Your backend parses it and attaches the answer to the ticket. Before sending, a moderator or support person matches the customer's error message to the rule the answer names, and checks the cited lines against the deployed version.

The session keeps every file the agent opened and every search it ran, so the reasoning behind each reply can be read later. The specs under spec/models/story_spec.rb and spec/models/domain_spec.rb are a natural next read if the answer is ever in doubt.

Run it on every new support ticket

Each ticket starts one POST /o/{org}/sessions from your help desk's webhook handler, with the question in input and the ticket id as the Idempotency-Key. The API answers 202 at once with the execution_id, which you store on the ticket.

With a webhook on the API key, your backend receives the reply when the run finishes and never polls. If the customer writes back with the exact error they saw, post it to the same session as a follow-up and the agent narrows the answer to that rule.

The use case this job follows, with its automation and trigger: Run an agent per customer task.

Why run it on Rush?

Rules like these live in model validations that only engineers read, and a moderation or support team ends up asking them each time. A Rush run starts with the Rails app cloned in its own sandbox, reads the validations for itself, and returns a reply with citations, without anyone on the team setting up Ruby 4.0 and the gems to look.

Each ticket gets its own run, and many run at once. Every reply cites the code it is based on and the session keeps the whole record, so a support person can send it with the same confidence an engineer would have, and the engineer can check it in a minute.

Frequently asked questions

Does the agent need to boot the Rails app?

No. This question is answered by reading app/models/story.rb and app/models/user.rb, and the prompt says not to change code. If a ticket needs a running app, the sandbox has a shell and the repository ships a docker-compose.yaml for development.

What if the customer hit a different rule?

The reply lists the rules that refuse a URL with their error messages, so the customer's message picks the right one. Sending the exact error in the prompt makes the answer specific.

Can it tell the customer when the restriction ends?

Yes, when the code says. Here is_new? compares created_at with NEW_USER_DAYS.days.ago, and NEW_USER_DAYS is 70, so the reply can say the rule stops applying 70 days after the account was created.

Where does the JSON arrive?

In data.result of the run.completed webhook, up to 16 KiB, and in result on GET /o/{org}/sessions/{id}. Parse and validate it in your backend before it reaches a customer.