MA
manager.addict.bestHybrid agent apps · ready to run

Content Factory Agent

Captions + AI covers + FFmpeg uniquify + AutoSocial queue handoff with three-state QA.

simplified-cliFFmpegskillsqueueQA

Hybrid components (≥5)

Asset factory → queue handoff.

  • simplified-cli — AI cover image
  • FFmpeg — uniquify vertical social video
  • Aaron/Corey skills — caption variants + claim filter
  • AutoSocial queue item — JSON handoff
  • Three-state QA — PASS/FAIL/INCONCLUSIVE exit codes

Runnable content agent

python · content_agent.py
#!/usr/bin/env python3
"""Content Factory Agent
Hybrids: simplified-cli · FFmpeg · Aaron/Corey caption skills · AutoSocial queue · three-state QA
"""
from __future__ import annotations
import json, os, subprocess
from dataclasses import dataclass, asdict
from pathlib import Path
from typing import Literal

Verdict = Literal["PASS", "FAIL", "INCONCLUSIVE"]

@dataclass
class R:
    name: str
    verdict: Verdict
    detail: str
    evidence: dict

def sh(cmd, timeout=180) -> R:
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
        ok = p.returncode == 0
        return R(cmd[0], "PASS" if ok else "FAIL", (p.stdout or p.stderr)[-400:], {"code": p.returncode})
    except FileNotFoundError as e:
        return R(cmd[0], "INCONCLUSIVE", str(e), {})
    except subprocess.TimeoutExpired:
        return R(cmd[0], "INCONCLUSIVE", "timeout", {})

def caption_batch(topic: str, n: int = 5) -> R:
    # Marketing-skills style variants
    variants = [f"{topic} — angle {i+1}: concrete outcome, soft CTA." for i in range(n)]
    banned = ["guaranteed", "risk-free riches"]
    for v in variants:
        if any(b in v.lower() for b in banned):
            return R("captions", "FAIL", "BLOCK claim", {"verdict": "BLOCK"})
    path = Path(os.environ.get("OUT_DIR", ".")) / "captions.json"
    path.write_text(json.dumps(variants, indent=2))
    return R("captions", "PASS", f"{n} variants", {"verdict": "SHIP", "path": str(path)})

def main():
    out = Path(os.environ.get("OUT_DIR", "./content_out"))
    out.mkdir(parents=True, exist_ok=True)
    topic = os.environ.get("TOPIC", "AI workflow for solo founders")
    media = Path(os.environ.get("MEDIA_IN", "in.mp4"))
    results = [caption_batch(topic)]

    # simplified-cli image (optional)
    if os.environ.get("SIMPLIFIED_API_KEY"):
        results.append(sh(["simplified", "ai-image:generate", "--wait", "--prompt", topic, "--out", str(out / "cover.png")]))
    else:
        results.append(R("simplified-cli", "INCONCLUSIVE", "no API key", {}))

    # FFmpeg uniquify if media exists
    if media.exists():
        dst = out / "unique.mp4"
        results.append(sh([
            "ffmpeg", "-y", "-i", str(media),
            "-vf", "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920",
            "-c:v", "libx264", "-crf", "20", "-c:a", "aac", "-ar", "48000", "-shortest", str(dst),
        ], 300))
        q = {
            "platform": "tiktok",
            "media": str(dst),
            "caption": json.loads((out / "captions.json").read_text())[0],
            "own_content_only": True,
            "source": "content-factory",
        }
        (out / "queue_item.json").write_text(json.dumps(q, indent=2))
        results.append(R("autosocial-queue", "PASS", "queue_item.json", q))
    else:
        results.append(R("ffmpeg", "INCONCLUSIVE", f"missing {media}", {}))

    fails = [r for r in results if r.verdict == "FAIL"]
    inc = [r for r in results if r.verdict == "INCONCLUSIVE"]
    status = "FAIL" if fails else ("INCONCLUSIVE" if inc else "PASS")
    report = {"status": status, "all_pass": status == "PASS", "results": [asdict(r) for r in results]}
    (out / "content_report.json").write_text(json.dumps(report, indent=2))
    print(json.dumps(report, indent=2))
    raise SystemExit(0 if report["all_pass"] else 2)

if __name__ == "__main__":
    main()