Dev.to AI 🤖 Ai 👁 0 📖 8 min read

Unlocking Creative Potential: A Guide to Using LLMs for Arts and Design

We are building an Art Direction Agent that turns a loose creative brief into a structured design document with color palettes, typography, and image generation prompts. It helps freelance designers and creative teams mo

We are building an Art Direction Agent that turns a loose creative brief into a structured design document with color palettes, typography, and image generation prompts. It helps freelance designers and creative teams move from text to visual direction without staring at a blank page. We will wire it to Oxlo.ai so every step runs through a single flat-rate request, which keeps costs predictable even when we paste in long brand briefs.

What you'll need

Because Oxlo.ai charges per request rather than per token, you can feed the agent multi-page briefs without watching metered costs scale with word count. See https://oxlo.ai/pricing for plan details.

Step 1: Initialize the Oxlo.ai client and system prompt

I start by pinning the system prompt so the model stays in art director mode. This persona forces JSON output and keeps responses structured.

You are a senior art director. You translate creative briefs into structured design direction. Always respond with valid JSON. Be concise and specific. Use Google Fonts names for typography and valid hex codes for colors.

Then I initialize the client. I use Llama 3.3 70B because it handles long context and structured instructions reliably.

from openai import OpenAI
import json

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

SYSTEM_PROMPT = """You are a senior art director. You translate creative briefs into structured design direction. Always respond with valid JSON. Be concise and specific. Use Google Fonts names for typography and valid hex codes for colors."""

class ArtDirector:
    def __init__(self):
        self.client = client
        self.system_prompt = SYSTEM_PROMPT

    def _ask(self, user_message: str) -> str:
        response = self.client.chat.completions.create(
            model="llama-3.3-70b",
            messages=[
                {"role": "system", "content": self.system_prompt},
                {"role": "user", "content": user_message},
            ],
        )
        return response.choices[0].message.content

Step 2: Extract structured constraints from the raw brief

Next I add a method that distills a messy paragraph into a strict JSON schema. This makes downstream prompts easier to compose.

from openai import OpenAI
import json

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

SYSTEM_PROMPT = """You are a senior art director. You translate creative briefs into structured design direction. Always respond with valid JSON. Be concise and specific. Use Google Fonts names for typography and valid hex codes for colors."""

class ArtDirector:
    def __init__(self):
        self.client = client
        self.system_prompt = SYSTEM_PROMPT

    def _ask(self, user_message: str) -> str:
        response = self.client.chat.completions.create(
            model="llama-3.3-70b",
            messages=[
                {"role": "system", "content": self.system_prompt},
                {"role": "user", "content": user_message},
            ],
        )
        return response.choices[0].message.content

    def parse_brief(self, brief_text: str) -> dict:
        prompt = (
            "Analyze this creative brief and return JSON with keys: "
            "project_name (string), audience (string), tone (string), "
            "visual_style (string), key_message (string). "
            f"Brief: {brief_text}"
        )
        raw = self._ask(prompt)
        return json.loads(raw)

Step 3: Generate color palette and typography

Now I generate the visual system. I feed the structured constraints back into the model so the palette and fonts match the audience and tone.

from openai import OpenAI
import json

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

SYSTEM_PROMPT = """You are a senior art director. You translate creative briefs into structured design direction. Always respond with valid JSON. Be concise and specific. Use Google Fonts names for typography and valid hex codes for colors."""

class ArtDirector:
    def __init__(self):
        self.client = client
        self.system_prompt = SYSTEM_PROMPT

    def _ask(self, user_message: str) -> str:
        response = self.client.chat.completions.create(
            model="llama-3.3-70b",
            messages=[
                {"role": "system", "content": self.system_prompt},
                {"role": "user", "content": user_message},
            ],
        )
        return response.choices[0].message.content

    def parse_brief(self, brief_text: str) -> dict:
        prompt = (
            "Analyze this creative brief and return JSON with keys: "
            "project_name (string), audience (string), tone (string), "
            "visual_style (string), key_message (string). "
            f"Brief: {brief_text}"
        )
        raw = self._ask(prompt)
        return json.loads(raw)

    def design_visual_system(self, constraints: dict) -> dict:
        prompt = (
            "Based on these design constraints, return JSON with: "
            "color_palette (array of objects, each with name and hex), "
            "heading_font (string), body_font (string), "
            "mood_keywords (array of strings). "
            "Constraints: " + json.dumps(constraints)
        )
        raw = self._ask(prompt)
        return json.loads(raw)

Step 4: Draft mood board image prompts

I want three concrete text-to-image prompts I can drop into Oxlo.ai's image generation endpoint or Flux.1. I pass both the constraints and the visual system so the prompts stay coherent with the palette and fonts.

from openai import OpenAI
import json

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

SYSTEM_PROMPT = """You are a senior art director. You translate creative briefs into structured design direction. Always respond with valid JSON. Be concise and specific. Use Google Fonts names for typography and valid hex codes for colors."""

class ArtDirector:
    def __init__(self):
        self.client = client
        self.system_prompt = SYSTEM_PROMPT

    def _ask(self, user_message: str) -> str:
        response = self.client.chat.completions.create(
            model="llama-3.3-70b",
            messages=[
                {"role": "system", "content": self.system_prompt},
                {"role": "user", "content": user_message},
            ],
        )
        return response.choices[0].message.content

    def parse_brief(self, brief_text: str) -> dict:
        prompt = (
            "Analyze this creative brief and return JSON with keys: "
            "project_name (string), audience (string), tone (string), "
            "visual_style (string), key_message (string). "
            f"Brief: {brief_text}"
        )
        raw = self._ask(prompt)
        return json.loads(raw)

    def design_visual_system(self, constraints: dict) -> dict:
        prompt = (
            "Based on these design constraints, return JSON with: "
            "color_palette (array of objects, each with name and hex), "
            "heading_font (string), body_font (string), "
            "mood_keywords (array of strings). "
            "Constraints: " + json.dumps(constraints)
        )
        raw = self._ask(prompt)
        return json.loads(raw)

    def write_image_prompts(self, constraints: dict, visual_system: dict) -> dict:
        prompt = (
            "Write 3 detailed text-to-image prompts for a mood board based on the "
            "project constraints and visual system. Return JSON with image_prompts "
            "(array of 3 strings). Each prompt should describe composition, lighting, "
            "color mood, and subject. "
            "Constraints: " + json.dumps(constraints) + "\n"
            "Visual System: " + json.dumps(visual_system)
        )
        raw = self._ask(prompt)
        return json.loads(raw)

Step 5: Orchestrate the pipeline and output the report

Finally, I wire the methods together in a single run flow. The finished script reads a brief, calls Oxlo.ai three times in sequence, and prints one consolidated art direction document.

from openai import OpenAI
import json

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

SYSTEM_PROMPT = """You are a senior art director. You translate creative briefs into structured design direction. Always respond with valid JSON. Be concise and specific. Use Google Fonts names for typography and valid hex codes for colors."""

class ArtDirector:
    def __init__(self):
        self.client = client
        self.system_prompt = SYSTEM_PROMPT

    def _ask(self, user_message: str) -> str:
        response = self.client.chat.completions.create(
            model="llama-3.3-70b",
            messages=[
                {"role": "system", "content": self.system_prompt},
                {"role": "user", "content": user_message},
            ],
        )
        return response.choices[0].message.content

    def parse_brief(self, brief_text: str) -> dict:
        prompt = (
            "Analyze this creative brief and return JSON with keys: "
            "project_name (string), audience (string), tone (string), "
            "visual_style (string), key_message (string). "
            f"Brief: {brief_text}"
        )
        raw = self._ask(prompt)
        return json.loads(raw)

    def design_visual_system(self, constraints: dict) -> dict:
        prompt = (
            "Based on these design constraints, return JSON with: "
            "color_palette (array of objects, each with name and hex), "
            "heading_font (string), body_font (string), "
            "mood_keywords (array of strings). "
            "Constraints: " + json.dumps(constraints)
        )
        raw = self._ask(prompt)
        return json.loads(raw)

    def write_image_prompts(self, constraints: dict, visual_system: dict) -> dict:
        prompt = (
            "Write 3 detailed text-to-image prompts for a mood board based on the "
            "project constraints and visual system. Return JSON with image_prompts "
            "(array of 3 strings). Each prompt should describe composition, lighting, "
            "color mood, and subject. "
            "Constraints: " + json.dumps(constraints) + "\n"
            "Visual System: " + json.dumps(visual_system)
        )
        raw = self._ask(prompt)
        return json.loads(raw)

    def run(self, brief_text: str) -> dict:
        constraints = self.parse_brief(brief_text)
        visual_system = self.design_visual_system(constraints)
        images = self.write_image_prompts(constraints, visual_system)

        return {
            "project": constraints.get("project_name", "Untitled"),
            "brief_summary": constraints,
            "visual_system": visual_system,
            "mood_board_prompts": images["image_prompts"],
        }

if __name__ == "__main__":
    director = ArtDirector()
    brief = (
        "A sustainable coffee brand targeting remote workers. "
        "The vibe should be warm, focused, and earthy but modern. "
        "Key message: fuel your flow state ethically."
    )
    report = director.run(brief)
    print(json.dumps(report, indent=2))

Run it

Save the file as art_director.py, export your key, and execute:

export OXLO_API_KEY="sk-..."
python art_director.py

Example output:

{
  "project": "Sustainable Remote Worker Coffee",
  "brief_summary": {
    "project_name": "Sustainable Remote Worker Coffee",
    "audience": "Remote workers aged 25 to 40",
    "tone": "Warm, focused, approachable",
    "visual_style": "Earthy minimalism with modern tech accents",
    "key_message": "Fuel your flow state ethically"
  },
  "visual_system": {
    "color_palette": [
      {"name": "Loam", "hex": "#5D4037"},
      {"name": "Oat Milk", "hex": "#F5F5DC"},
      {"name": "Deep Forest", "hex": "#2E4A3E"},
      {"name": "Copper Accent", "hex": "#B87333"}
    ],
    "heading_font": "Montserrat",
    "body_font": "Merriweather",
    "mood_keywords": ["cozy", "focused", "organic", "minimal", "ethical"]
  },
  "mood_board_prompts": [
    "A sunlit home office desk with a ceramic pour-over coffee setup, lush green plants in the background, warm earth tones, shallow depth of field, shot on film",
    "Aerial view of sustainable coffee farm meeting a modern glass coworking space, split composition, soft morning light, muted greens and browns",
    "Close-up of hands holding a matte black reusable coffee cup, laptop screen glowing softly in background, bokeh city lights, warm and focused atmosphere"
  ]
}

Wrap-up

Try swapping the model string to qwen-3-32b or kimi-k2.6 to see how different Oxlo.ai models interpret the same brief. As a next step, pipe the generated image prompts into Oxlo.ai's images/generations endpoint using oxlo.ai-image-pro or flux-1 to render the mood board automatically.

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.